Libsodium decryption returns empty response - php

I can't get Libsodium to decrypt a response I'm receiving from a webhook but openssl_decrypt does. I'm not getting an error but I keep getting a blank result which mean I must be doing something wrong.
The reason I want to use Libsodium over OpenSSL is that it's more reliable. In high traffic scenarios, openssl_decrypt becomes quite unreliable.
Here's my code:
public function webhook(Request $request) {
$psp = new Psp();
$transaction_state = new \stdClass();
$transaction_state->state = 'Live';
$key_from_configuration = 'B46FAC78301751BCB489AC6D878877CA9AD8A71278DA777DD91B1AAB82135817';
$iv_from_http_header = $request->header('x-initialization-vector');
$auth_tag_from_http_header = $request->header('x-authentication-tag');
$http_body = file_get_contents('php://input');
$key = hex2bin($key_from_configuration);
$iv = hex2bin($iv_from_http_header);
$auth_tag = hex2bin($auth_tag_from_http_header);
$cipher_text = hex2bin($http_body.$auth_tag_from_http_header);
// This works when $cipher_text = hex2bin($http_body)
$result = openssl_decrypt($cipher_text, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $auth_tag);
// This does not work. According to the webhook docs, $cipher_text has to equal hex2bin($http_body.$auth_tag_from_http_header);
$result = sodium_crypto_aead_aes256gcm_decrypt($cipher_text, NULL, $iv, $key);
Storage::put('json.txt', $result);
}
The docs for the webhook aren't that great and the example they have is pre PHP v7.1. Here's their example code...
<?php
/* Php 7.1 or later */
$key_from_configuration = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
$iv_from_http_header = "000000000000000000000000";
$auth_tag_from_http_header = "CE573FB7A41AB78E743180DC83FF09BD";
$http_body = "0A3471C72D9BE49A8520F79C66BBD9A12FF9";
$key = hex2bin($key_from_configuration);
$iv = hex2bin($iv_from_http_header);
$auth_tag = hex2bin($auth_tag_from_http_header);
$cipher_text = hex2bin($http_body);
$result = openssl_decrypt($cipher_text, "aes-256-gcm", $key, OPENSSL_RAW_DATA, $iv, $auth_tag);
print($result);
/* Php prior to 7.1 */
/* Please refer Using Libsodium in PHP Projects */
$key_from_configuration = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
$iv_from_http_header = "000000000000000000000000";
$auth_tag_from_http_header = "CE573FB7A41AB78E743180DC83FF09BD";
$http_body = "0A3471C72D9BE49A8520F79C66BBD9A12FF9";
$key = hex2bin($key_from_configuration);
$iv = hex2bin($iv_from_http_header);
$cipher_text = hex2bin($http_body . $auth_tag_from_http_header);
$result = \Sodium\crypto_aead_aes256gcm_decrypt($cipher_text, NULL, $iv, $key);
print($result);
?>
Edit: Real world responses
Key: 282F8C1F40FD0BF4E9C130CB5E3CE6624B78E3AEB89FF4E4DFBF5F4360B1488B
IV: D71C4DE2ACEF0EEB40AEAA25
Auth Tag: CE27C16EA5A3D772DBB10A42C5DF99C9
Ciper: DA113CEBD4C6959DAA26B3A4FF4F66B8D403FF6042900F725567FF426A77E7EB46927B574D334A1655C6F631F8096D9E3D889D859E372147017A052F1FC714AA9512E2EAAF1C5375AA0902982215FC6D2F29B112A877EF42D8D70353B0A24D651EE8CA2B224B9310A761EF767C810F1217CF31446C4DD6EA0864ED8F5E99BE6C573FE435333FBDB28A124C66EC44F5B44C0F4FD5D73444B85E1EB20B4F72B4A92D4723928F412231D4AD92381599268AF736D8849B4B3204408D4BD0BA4A386931D31B2A00983FA5BE8054126F34C9FFA1D898203BAB35EE586A5136469B9DBDA391594948F0E5CB066F9F9D69B1D4D6009A93227D172D43D9FCC936B1BD05F2D568B361CAF445FBA7FDFDF651AFD3AADA107C3D6D8A26284D003D29CAD4E111BE6ABBE3AF74AB1F19AAFF3CD7C8CE1F5270CCC9E849AC6D9C4030233EF33EAC8925F7E533395D4B8AF33EA2EB8E22FD138AACE48E9B8A4C7276A7474CA3BED7297E1BBCD2518229143198D9AF0BF987C0E53E4FC4E41149AEA8A1E59559B4ACEC481C67B4F962368A794C687EEBCE0A110CDF2C8FBE53AB3E9E4A8F04FACC783B9974236436828729EB95249B98CDB498CF2A81BBDEF712BD517A44654864B4E083BC8B9ECE153F87E107D55ED279C61313D6E8E8F1C5757E5CC330EEB8F165FACEFC616862FB7644BF0FE5A640DE9A5FD48408CD7EDB697BDD77DD09DE98EEEC7594D8B4B7BED07828B7F1AFB357E160B3844414BA8764BA06B8318ED82943FB3D270F9DAA415E3A35B1A2E1D2523177831BE2FE793416707C88E4A9CAC2FD787541B40CBB08BED5702A6229DAD4C81855AE014B1AFD42B84AFD13065DC2508B5B8C1345CDF787188F6ADA880ED6CBA5002B4241DE8E27BE368CF1D7D17AAE83926A5BD1EF4815A764FD39A8C7326FCA2D87A1C102CCB51F1504310AD7BEFC6DF1B5A7707196E504D6170E520198EBBB6F1026433F99A4A0AD593064E602E83C16F25D7484AE9EE00C4EBA51F23104DC2B071B88D71763B38CD5E0446E25D8D633408F28315C9B250CF5ACCAA83DE6EE793A0FFDB2DB13A66572A170A7DB70E5BA3B62A4241C5E162FBCD2DAC2072D853A45CDB67883CA61EB11552AB8E8CE0DAC7B30656B808631AED23FB6FE3C8DA738ADB4B18B5F450CD62182A86CAB520C22A53155B9644C6967F657F78A89A11E98475FD4E691B90FC49DE5CF499780491FE001EE22972FDEB14A18C5A28B97F67976E0B662CF80B0A7693272C175A1CEE65AB4C72A5F8BB125D79AE7C1E654A63AECB4AC559368DF5859FACC6982A28569FB1FD1799B6430FB7351D3CF2BB69A1C2BFE72FEB731699D0D48449B15E95A6EAD7E4AD99EF72820E942D806BF52F9FC18E3D523C1F0F0236611ABD3F46B74734E52B7CE9EBAF240C11454E21E10AFED954C5DB61EF9063935E237AB774934FE1C1E1BC6ACBC5BDE49C792B86635EAC9820680DD44B6F13C0A79CD3249825998C85142C5E3BC681FAE0B9648975446F9836A13E9BFC969D870B2166C62CB25A6802563C6228F284343967F61EEF958EC2CEA5BC7E7905D1A516376B6D66A6DD583F1ED0352DC3BAC491645969F67ED3FFDE9C59F858A334A545F46F710B07728C7658C2E5D8B853DF91DA9B4902C3754D14ABF38CEBFF6B0B495C8B84FE256D3237733CA0D4AD61F09CE2736EC3E710C64372C94030B520B843384B4CB255BF3B76803DB754530A5B63BD20F5B786BFDED980015F9EE7F13376DECDD4FB5DF57459A8E5CAE76AF2F1A21A0C596A8246A1934FCFF5BC087D0EB4A07E7F4E0BF8E79214453110B123DB94D84A76C40199C3CFFE0D9087A59C795ADAAE49315F9AEAF48E79D30313D74B9CDDADD572857491E56EB08B020A0F68186FF28008A7E42FE9815DEE15D785AB094E0CEC12548406616D8FF08C2DDF19712929348ABFB8C1B56A23C29FAB9C4AD7F608ADA5BBC13B97E34C36B3E0E15A5D0D1E932BC7AFB239AB608ED8E60C539EEE06399FC7956E3C2DFA760627F9E98E3AE83B4C399E589410A72F05B1D90C9F839B477AE91C29D3E3925341DD3AD201176C7B22D58387C3E2DD7C920D1C900E254AE351C19EA6EE7350E2B4B1E287A8A35C3D0644F7DA83B252ADA4884473728418D6942AD60209A0899DA0B9246F9D937CAD009F1C82C1D15C31B1BEFE49CBC4273CF7882EB56B6D886969399733E1078A5376509DBAB8714EC44FF1307A380FE39CD58011AA6076CCB3FFA732429DFE5B48DBADB3CAF70D3B9A376C01CC38C3408C448BAC232555666157EB7FD0F2210C6E2586D80814E0E2AA9DDAD42C0EC0E4362726ACCF747987D7EC876030C352D10BBF16D845006AABB27CE4BDDDA28BEF4CB1932AD1CB2C839B8B41C692C4ECB666073D6C1AF8F1E7889FCA3BD53DA33E055413EE00E74C2131377DC980B2B66CC38C15A4BC21A4FE1E7093C7DF11DF534EE3FE702211FA02941E2F4FE8D68DBFD616A3978574C67302E5E1B05377DBCA080DEFCE218CEFC3DA5CEEC703D040BE2FCE2DE6CEB6B73845C65B627A5FAD0CF519016B80E1B9B2A41CE976DF75CD554FF356599469EBA4C06FFE4AD5CA56226CE3475FC02EAC07B7BDD4384CB02B5FA28DB094041B0DBD708681841E97F70A910CFA3267E0AA3608E0CD33E65A6F4F2C31AD48D74C64C4E51E8A327882439894A49EC4FBE2175076255D0053B7E4C2DD938937CC3820F44306EC087D3A38DE7D994D7265B491058036206D3A7C2654E9DA569E54DAE951E339C6A8F8BA1F1F179A83025EF8C207182DD7344399463B99B3991504447E353D02AF3359769CA10D6D0AB1870FB9D9BD9EA9F73A4A0A60008BF5150F0A1EEB7A7A2AB888EE8709C767CEC7F0FD2FF8A140B92E26615EECDC58EFD9DFE4EEB49EC9494D75A01A629554EBD2EBF183C12679CD3CEE09BB02ED7D4DC2D623AB3C965D2F6034D266A311CBFB8C8D4A1526A039E592944C6227AC276ED78D2259AC5F2B07D7C6FC02D29540D01136F91693005ACFD5DBAD06FF7E88434D73B3D1FB59D16E4B0EC5020D07567CF962F8437BDF365E601EC76CFD405D3A6FD4E3EE0A5044AA294AFAEAA26449E4C5BDD5A3610BF6F94DFBD4C415D
Key: 282F8C1F40FD0BF4E9C130CB5E3CE6624B78E3AEB89FF4E4DFBF5F4360B1488B
IV: 8C7A8CA57FA6EC8B78EFB4AE
Auth Tag: E2A22DA77F0C508403816A802AE00CEF
Ciper: 179DB919FBD81E8B3436724479F81CE83B4E6CBE41BCF585FD56C89C9B292BD7B140AE2582B456ED3990FDF2C2D02D3E46028185AF0271C54E089807D6C95B05F6D824BF8BF4DAA4B9423BD5688F19DDC3D592F67908C7F9DE03112422318A1C8E83247ACF7FA6D36C96995D1FE6C95696857C5E1F1F4B13D508ADD58DC3C14C000C7E23AFC677D10901CD19A0DCCBC19C87F80660E1C986DE0A258578B5105B9952FB2A59015BE7D6DC84095529A21E67EEE8DA29E8C7920862C5F729616C2EF4F7949E9E6529E29C49D26054B3234DA7501C18E7818CF8AA5CA1335A02438F0090BE9D22B1C5576535E9B2DF58765EDD0FBA629A86B8B9E0D2074EA5A0D5F2275CCF9EDAABF77C2E1CE1B74FCAC4F70991CB32F4309DBD59157D199F65B6FA84410C305F4DBD21288BD23A3A0A925F24F387C4F7B1527D5D9CDEE2B52090614D779DD0C4ED64ADDB395BAA5468B35889A0881D217F430681EE749DE0ABF8FCFA203CACB636A8A193EA716D503F8E60AE510A47A91B9A246528A89B665F18321F29AA3B3F0CA1952890ED562351EB3B20F71169872C44DDE54B71B79526A392EDF5941F88B8878525F002E1CCCC18E002C4EE779942931BD0AE4192497532F48939F3F4531EF2DDBD0893C79D060010D3C4943F71515D0BCDDE9AA497ACF8453325EC831F2269E16830BEF96D2B791F7570AF0313D7C35B8B1D69F7E1A127E110101A32B1B5669F51A07957A0968C7DE3A7294EED68B0EB661AFBB2384173D404708414731C4AC08C47FF128FAAA0E89C33B8BE9082B97C7A205989915489FC186D6931CE5A48A3E666D23A4BB0C37A07456037BD2EB9924FA714D149933B828BF1F74A7A6EA22979FAF7CE6F03247ED931656EFCDB891A2C7D781759FA9176D34E1244B9133297D42E8E3E3BAA066B218D5431C9CEA593ABD79E821A75634D13E0EAA50A626695AD6BC8DCA94812D4A44B90584803D6822F7BAB3C806454F7A88D1ADCE4D31F28914EEADD0E05F82BCB5E75503EF79E05ED3B0550B5D57A632226E9312232C6D1BE4B42D9
Key: 282F8C1F40FD0BF4E9C130CB5E3CE6624B78E3AEB89FF4E4DFBF5F4360B1488B
IV: 34227A5F7EF770D06AFF5802
Auth Tag: 0378EEE7AD576220256882D6084A4EAA
Ciper: 3B28A15C7103AB068A191618863C267E65A07AB9882BE0EF20CF32C137509D30E8066E26C7C2CE2C3F4DE2FB86E3A5409A90D2E772790434A789274ACCA93960CB65BF93066FC7D53CF7C74E8DEFE43A9DFB918F3F7109BF17F01C7378D44F24B78B15B8905DB06525A00135037B5B52E4F899D10111F3A2EBCA49A17C5272F98F97971051DCE89EBAF8412A585FE38B53DF4DEA2A9944CDAD2834F079A49F4247507253FD6AD769AB53F5C2B809B71C303D02E4321FD7A28F918FB4C0CF7963C2437D14A3273DDAB98231B15634D9E143D623B850FB8B8803717B4FDC647063C939DF677F6E90308F3824448179326C2C5AA1A2406B13F048BF908502D613DC1F2043D1A9AF13571287C8F4B98B5CE31E54D8E7BB0D963E451A5C0B9C2226B95967FCCA5AD754788C9F75080D458785B77AA6647A12F49FD07D7C3EFA79C6145E61AD101F3427920288891E6BFD05289D98CE030D5CCCDC55016A231B60E118127AFA49B9DB1FFD413DEFCEE72CD1361580F969811EA5AA31E4F5C095C5D12038D1BADDF1A6605B05EE4BF4009929E44F24017DD64D59B75381458BAC548BBDFC2F2AEF7CAE79A8EE0524747B69DD8C257521ED43CE4F9EBCCF2ADF7F708B53764177B49FFD8D8311F47A015A77FF2B2913F781C86C2E5D5ACBE866E18F6E859A118980DACAF3880722F95B75584B0B5171B8BC42309FD58C09F459818E33E49064D9436A6BD4F2F0E13EBBB2465C407711E6C9F2B47FE958B867A5AE433D7BBB164EBD847675480A1275093A1339C921EF527519B41550FF34B7BBB1EBD2DC4A1EC1A5DD3067D0BFC27AB5B527DC7BD388A66C1EBF4CAE403976834174E4681B66DFF867FAB023EC88567A60D8235ED8A0F55EEFF48602E9826C762E47B4441B18C378B529FFF002AEE98497974EA916699FD511C3D0FBE1FB4A6FA2721F3B614F9DFF2592CEF21CB25CE8057326AE6ECE484367B5EDBEF91424FD599F731B316626C51728A045FC2C7F1D01

Your simplified example, using both OpenSSL and Libsodium, producing the same output:
$key = hex2bin("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f");
$nonce = hex2bin("000000000000000000000000");
$tag = hex2bin("CE573FB7A41AB78E743180DC83FF09BD");
$ciphertext = hex2bin("0A3471C72D9BE49A8520F79C66BBD9A12FF9");
$msg = openssl_decrypt($ciphertext, "aes-256-gcm", $key, OPENSSL_RAW_DATA, $nonce, $tag);
assert($msg === '{"type":"PAYMENT"}');
$msg = sodium_crypto_aead_aes256gcm_decrypt($ciphertext . $tag, NULL, $nonce, $key);
assert($msg === '{"type":"PAYMENT"}');
Update: with your real-world data:
$key = hex2bin("282F8C1F40FD0BF4E9C130CB5E3CE6624B78E3AEB89FF4E4DFBF5F4360B1488B");
$nonce = hex2bin("34227A5F7EF770D06AFF5802");
$tag = hex2bin("0378EEE7AD576220256882D6084A4EAA");
$ciphertext = hex2bin("3B28A15C7103AB068A191618863C267E65A07AB9882BE0EF20CF32C137509D30E8066E26C7C2CE2C3F4DE2FB86E3A5409A90D2E772790434A789274ACCA93960CB65BF93066FC7D53CF7C74E8DEFE43A9DFB918F3F7109BF17F01C7378D44F24B78B15B8905DB06525A00135037B5B52E4F899D10111F3A2EBCA49A17C5272F98F97971051DCE89EBAF8412A585FE38B53DF4DEA2A9944CDAD2834F079A49F4247507253FD6AD769AB53F5C2B809B71C303D02E4321FD7A28F918FB4C0CF7963C2437D14A3273DDAB98231B15634D9E143D623B850FB8B8803717B4FDC647063C939DF677F6E90308F3824448179326C2C5AA1A2406B13F048BF908502D613DC1F2043D1A9AF13571287C8F4B98B5CE31E54D8E7BB0D963E451A5C0B9C2226B95967FCCA5AD754788C9F75080D458785B77AA6647A12F49FD07D7C3EFA79C6145E61AD101F3427920288891E6BFD05289D98CE030D5CCCDC55016A231B60E118127AFA49B9DB1FFD413DEFCEE72CD1361580F969811EA5AA31E4F5C095C5D12038D1BADDF1A6605B05EE4BF4009929E44F24017DD64D59B75381458BAC548BBDFC2F2AEF7CAE79A8EE0524747B69DD8C257521ED43CE4F9EBCCF2ADF7F708B53764177B49FFD8D8311F47A015A77FF2B2913F781C86C2E5D5ACBE866E18F6E859A118980DACAF3880722F95B75584B0B5171B8BC42309FD58C09F459818E33E49064D9436A6BD4F2F0E13EBBB2465C407711E6C9F2B47FE958B867A5AE433D7BBB164EBD847675480A1275093A1339C921EF527519B41550FF34B7BBB1EBD2DC4A1EC1A5DD3067D0BFC27AB5B527DC7BD388A66C1EBF4CAE403976834174E4681B66DFF867FAB023EC88567A60D8235ED8A0F55EEFF48602E9826C762E47B4441B18C378B529FFF002AEE98497974EA916699FD511C3D0FBE1FB4A6FA2721F3B614F9DFF2592CEF21CB25CE8057326AE6ECE484367B5EDBEF91424FD599F731B316626C51728A045FC2C7F1D01");
$msg = sodium_crypto_aead_aes256gcm_decrypt($ciphertext . $tag, NULL, $nonce, $key);
var_dump($msg);
As a side note, you should use sodium_hex2bin() instead of hex2bin() when decoding sensitive data, and if you are using the PECL libsodium extension, sodium_crypto_aead_aes256gcm_decrypt_detached() lets you provide the ciphertext and the tag as distinct parameters instead of having to concatenate them.

Related

Decrypt AES-256-CBC string that is encrypted with NodeJS

I use the following functions to encrypt/decrypt with NodeJS, they work fine. But I was unable to decrypt the data with PHP to use in some part of the same project.
NodeJS:
function encrypt(text){
var cipher = crypto.createCipher('aes-256-cbc','strong-key')
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
return crypted;
}
function decrypt(text){
var decipher = crypto.createDecipher('aes-256-cbc','strong-key')
var dec = decipher.update(text,'hex','utf8')
dec += decipher.final('utf8');
return dec;
}
What I tried with PHP is:
openssl_decrypt('fdf32748aa4ce37fc600bbe7be14bfc7', 'AES-256-CBC', "strong-key");
But it keeps returning false/empty. I appreciate healping me to know what I am doing wrong.
Edit:
For example, decrypting 28e1dfdedac467a015a9c8720d0a6451 with PHP should return "Hello World", using the same key as above.
Make sure that your incoming data is the correct format (ie doesn't have any extra layers of encoding). It looks like hex but it's not what openssl_decrypt necessarily expects.
Here's a back and forth PHP example (using an IV which you should too):
$data = 'hello this is some data';
$key = 'this is a cool and secret password';
$iv = random_bytes(16);
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, 0, $iv);
echo 'iv (as hex): ', bin2hex($iv), PHP_EOL;
echo 'encrypted: ', $encrypted, PHP_EOL; // note this is not hex
$decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', $key, 0, $iv);
echo 'decrypted: ', $decrypted, PHP_EOL;
$ php test.php
iv (as hex): 02c00788438518f241cb86dc90237102
encrypted: oRZAXMjNle6hkJ9rTHTeUl5VoHQol+020Q/iFnbgbeU=
decrypted: hello this is some data
Edit, even more specific example, highlighting the importance of knowing your encodings:
// test.js
const crypto = require('crypto');
let data = 'hello this is some data';
const key = crypto.scryptSync('Password used to generate key', '', 32); // 256 / 8 = 32
const iv = crypto.randomBytes(16); // Initialization vector.
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let crypted = cipher.update(data,'utf8','hex')
crypted += cipher.final('hex');
console.log('data: ', data);
console.log('key: ', key.toString('hex')); // key: 9266bc531befd01b6a55c232fa0efeb35625079e7024758b2e65d0dd72fe59df
console.log('crypted (as hex): ', crypted); // crypted (as hex): b571d864da0680d77e4880d0071b49e456a1eead4b1cbfa42a9337965a466362
console.log('iv (as hex): ', iv.toString('hex')); // iv (as hex): 788ac1dcee25824b713b5201d07cc133
Here we know all our outputs are hex, so we can re-format them to binary data on the PHP side:
// test.php
$iv = hex2bin( '788ac1dcee25824b713b5201d07cc133' );
$encrypted = hex2bin( 'b571d864da0680d77e4880d0071b49e456a1eead4b1cbfa42a9337965a466362' );
$key = hex2bin('9266bc531befd01b6a55c232fa0efeb35625079e7024758b2e65d0dd72fe59df');
$decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
echo 'decrypted: ', $decrypted, PHP_EOL; // hello this is some data
Final Edit: Now with working key derivation implementation. This successfully decrypts your 'Hello world':
$password = 'strong-key';
// derrive key and IV using function from SO, which implements same method node uses
$ar = deriveKeyAndIV($password, 1, 'aes-256-cbc', 'md5');
$key = $ar['key'];
$iv = $ar['iv'];
$decrypted = openssl_decrypt(hex2bin('28e1dfdedac467a015a9c8720d0a6451'), 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
echo 'decrypted: ', $decrypted, PHP_EOL; // Hello world
function deriveKeyAndIV($data,$count,$cipher,$digest) {
$ivlen = openssl_cipher_iv_length($cipher);
$keylen = 32;
$hash = "";
$hdata = "";
while(strlen($hash) < $keylen+$ivlen) {
$hdata .= $data;
$md_buf = openssl_digest($hdata, $digest);
//
for ($i = 1; $i < $count; $i++) {
$md_buf = openssl_digest ( hex2bin($md_buf),$digest);
}
$hdata = hex2bin($md_buf);
$hash .= $hdata;
}
//
$key = substr($hash,0,$keylen);
$iv = substr($hash,$keylen,$ivlen);
//
return array('key' => $key, 'iv' => $iv);
}

Cannot find the right 3DES cipher in PHP

I am trying to compute a PHP function to have the 3DES (Triple DES) in ECB Mode. But I am getting the wrong result.
My result : 615EDC0E8EAD5DDE
Expected result : 7B66D9A5010A8035
(the expected result is computed with HSM and confirmed with the website) http://tripledes.online-domain-tools.com/
Here is my PHP function, taking as parameters :
$data = "3200000025381234"
$key = "98137332E06BBA25AEE51CFD150EA8E3"
function tripleDES($data, $key) {
$key= hex2bin($key);
$data = hex2bin($data);
$enc = openssl_encrypt($data, 'des-ede3', $key, OPENSSL_RAW_DATA |
OPENSSL_ZERO_PADDING);
return strtoupper(bin2hex($enc));
}
What am I doing wrong ?
Thanks to the answer of Topaco, I understood my mistake.
So I used this github project: https://github.com/gilfether/phpcrypt and corrected my code this way (using my 16-bytes key):
function triple_DES($data, $key){
$key = hex2bin($key);
$data = hex2bin($data);
$crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_3DES, PHP_Crypt::MODE_ECB);
$encrypt = $crypt->encrypt($data);
return strtoupper(bin2hex($encrypt));
}

How to implement Crypt::encrypt method manually in PHP?

I try to implement Crypt::encrypt function in php and this code is here:
$key = "ygXa6pBJOWSAClY/J6SSVTjvJpMIiPAENiTMjBrcOGw=";
$iv = random_bytes(16);
$value = \openssl_encrypt(serialize('123456'), 'AES-256-CBC', $key, 0, $iv);
bIv = base64_encode($iv);
$mac = hash_hmac('sha256', $bIv.$value, $key);
$c = ['iv'=>$bIv,'value'=>$value,'mac'=>$mac];
$json = json_encode($c);
$b = base64_encode($json);
But result is wrong.
I am thinking i should do something on $key before set in openssl_encrypt function.
Please help.
Thank you.
SOLVED:
We can implement this method like this:
$text = '123456';
$key = "ygXa6pBJOWSAClY/CFEdOTjvJpMIiPAMQiTMjBrcOGw=";
$key = (string)base64_decode($key);
$iv = random_bytes(16);
$value = \openssl_encrypt(serialize($text), 'AES-256-CBC', $key, 0, $iv);
$bIv = base64_encode($iv);
$mac = hash_hmac('sha256', $bIv.$value, $key);
$c_arr = ['iv'=>$bIv,'value'=>$value,'mac'=>$mac];
$json = json_encode($c_arr);
$crypted = base64_encode($json);
echo $crypted;
This work tor me.
enjoy :)
Be Successful
Here is the implementation, directly from the official source code.
public function encrypt($value)
{
$iv = random_bytes(16);
$value = \openssl_encrypt(serialize($value), $this->cipher, $this->key, 0, $iv);
if ($value === false) {
throw new EncryptException('Could not encrypt the data.');
}
// Once we have the encrypted value we will go ahead base64_encode the input
// vector and create the MAC for the encrypted value so we can verify its
// authenticity. Then, we'll JSON encode the data in a "payload" array.
$mac = $this->hash($iv = base64_encode($iv), $value);
$json = json_encode(compact('iv', 'value', 'mac'));
if (! is_string($json)) {
throw new EncryptException('Could not encrypt the data.');
}
return base64_encode($json);
}
$iv should be the same as in the source
$this->key is the encryption key you set in your .env file, encoded in b64
$this->cipher should be the one you configured in your laravel configurations and compatible to your key-length.
In your example, you have set your $key to the value after the "base64:"-string, which is not the key. You need to encode the key with base64 before passing it.
So the the $key to the base64 encode of ygXa6pBJOWSAClY/J6SSVTjvJpMIiPAENiTMjBrcOGw=, which is eWdYYTZwQkpPV1NBQ2xZL0o2U1NWVGp2SnBNSWlQQUVOaVRNakJyY09Hdz0K

Why does file encryption using mcrypt fail?

I have an issue using mcrypt to encrypt a file on filesystem to e.g. store it into Mysql database. I have reduced the issue to the following lines of code:
<?php
$key = vzc_generateKey();
$file_content = file_get_contents("test.pdf"); // Fails
$file_content = file_get_contents("test2.docx"); // Fails
//$file_content = "12323"; // Works great
$hash_start = md5($file_content);
$encrypt = vzc_encryptV3($file_content, $key);
$decrypt = vzc_decryptV3($encrypt, $key);
$hash_end = md5($decrypt);
echo ($hash_end == $hash_start)."##";
function vzc_generateKey()
{
$cstrong = false;
while ($cstrong == false)
{
$bytes = openssl_random_pseudo_bytes(16, $cstrong);
}
return bin2hex($bytes);
}
function vzc_decryptV3($crypt,$key) {
$content = base64_decode($crypt['crypt']);
$iv = $crypt['iv'];
$rijndael = 'rijndael-256';
$cp = mcrypt_module_open($rijndael, '', 'ofb', '');
$ks = mcrypt_enc_get_key_size($cp);
$key = substr(md5($key), 0, $ks);
mcrypt_generic_init($cp, $key, $iv);
$decrypted = mdecrypt_generic($cp, $content);
mcrypt_generic_deinit($cp);
mcrypt_module_close($cp);
return trim(base64_decode($decrypted));
}
function vzc_encryptV3($file_content,$key) {
$content = base64_encode($file_content);
$rijndael = 'rijndael-256';
$cp = mcrypt_module_open($rijndael, '', 'ofb', '');
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($cp), MCRYPT_RAND);
else
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($cp), MCRYPT_DEV_RANDOM);
$ks = mcrypt_enc_get_key_size($cp);
$key = substr(md5($key), 0, $ks);
mcrypt_generic_init($cp, $key, $iv);
$encrypted = mcrypt_generic($cp, $content);
$returnvalue = array("crypt"=>trim(base64_encode($encrypted)), "iv"=>$iv);
mcrypt_generic_deinit($cp);
mcrypt_module_close($cp);
return $returnvalue;
}
?>
Using the String "12323" everything works fine, both Hashes do equal. But those two test files (one pdf and one docx) fail. It seems that the decryption returns different values then the origin data.
What can I do to solve this issue?
Thank you very much in advance for any tip you can provide.
It is probably the fact that the files are not exactly n * blocksize long. This leads the algorithm to pad the end of the file with '\0' and this changes the content of the file when you do the md5 calculation.
One way around this is to strip the padding off of the last block, if you can reliably find the end of the file.

How to create two way encode/decode methods using use-specific key - PHP?

I need two functions/methods, one to encode, one to decode. This is not for storing passwords. Each user will have a specific key/salt to encode the data.
This is how I would like it to work:
function encode($str, $key) {
// something fancy
}
function decode($str, $key) {
// something fancy
}
$key = $logged_in_user->get_key();
$plain = 'abc abc 123 123';
$encoded_data = encode($plain, $key);
// some_fancy_encrypted_data_that_is_really_cooooool
$decoded_data = decode($encoded_data, $key);
// abc abc 123 123
Another thing is that every time I use this function it needs to return the same thing every time I use the encode function with the same user key.
How would I do this??
$myVarIWantToEncodeAndDecode
Define key (salt, broth etc..): $key = "#&$sdfdfs789fs7d";
To encode:
$encoded = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $myVarIWantToEncodeAndDecode, MCRYPT_MODE_CBC, md5(md5($key))));
To decode:
$decoded = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($encoded), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
Note: mcrypt_decrypt has been DEPRECATED as of PHP 7.1.0. Relying on this function is highly discouraged.
Use openssl_encrypt instead of mcrypt_encrypt
mcrypt_encrypt DEPRECATED as of PHP 7.1.0 and REMOVED as of PHP 7.2.0.
So, Try this..
function encrypt_decrypt($string, $action = 'encrypt')
{
$encrypt_method = "AES-256-CBC";
$secret_key = 'AA74CDCC2BBRT935136HH7B63C27'; // user define private key
$secret_iv = '5fgf5HJ5g27'; // user define secret key
$key = hash('sha256', $secret_key);
$iv = substr(hash('sha256', $secret_iv), 0, 16); // sha256 is hash_hmac_algo
if ($action == 'encrypt') {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
} else if ($action == 'decrypt') {
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
echo "Your Encrypted password is = ". $pwd = encrypt_decrypt('spaceo', 'encrypt');
echo "Your Decrypted password is = ". encrypt_decrypt($pwd, 'decrypt');

Categories