I'm currently stuck here right now, this is from client side:
$scope.encryptFormData = function() {
// Get payment data
var paymentData = JSON.stringify($scope.payment);
// Generate AES secret key
var secret_key = $scope.generateKey(paymentData);
var iv = CryptoJS.lib.WordArray.random(16);
// Encrypt form data using AES secret key
var cipherPaymentData = CryptoJS.AES.encrypt(paymentData, secret_key, {iv: iv});
// Encrypt AES secret key with RSA public key from server
var secret_key_rsa = null;
var encrypt = new JSEncrypt();
encrypt.setPublicKey($scope.public_key);
secret_key_rsa = encrypt.encrypt(secret_key);
// Assign values to form object
var iv_hex = CryptoJS.enc.Hex.stringify(iv);
var payment_data_hex = CryptoJS.enc.Hex.stringify(cipherPaymentData.ciphertext);
$scope.payment_data.secret_key = secret_key_rsa;
$scope.payment_data.iv = iv_hex;
$scope.payment_data.payment = payment_data_hex;
// Send form data to server
};
$scope.generateKey = function(p) {
var salt = CryptoJS.lib.WordArray.random(128/8);
return CryptoJS.PBKDF2(p, salt, { keySize: 512/32, iterations: 1000 });
}
Now, I send this payload to the server for decryption:
{
iv: "ae3bafa370bdc0c8a6b47ab1b792ec58"
payment: "e12f9db635984ec2f146bd34e433ef912580c4b3c7c1efe0a8e3fa6981abefa860630752539a9af88a9db0c198a63b804855d4b56357f75456785d7313908c6e"
secret_key: "emMKQ2QOWtzQAHhur4FLQCyBSK9zzPzomjWyDbeOM3VpjIKb1aNs9SL4P1nhuizEwuM2os/FXsN6MJz/cwxQWakK3tnVFvmt..."
}
This is my controller function in the server:
public function storePayment(Request $request) {
$postData = $request->data;
// Decrypt AES secret key, using private key
$iv = $postData['iv'];
$secretKey = $this->EncryptionService->decryptData($postData['secret_key']);
// Decrypt AES client form data with secret key
$paymentData = $this->EncryptionService->decryptSecretData($postData['payment'], $secretKey, $iv);
// Print decrypted data
}
From my EncryptionService:
For RSA decryption:
public function decryptData($data)
{
$privateKey = $this->getPrivateKey();
if (empty($privateKey)) {
$this->regenerateKeypair();
}
$privateKey = $this->getPrivateKey();
$binaryData = hex2bin($data);
openssl_private_decrypt($binaryData, $decrypted, $privateKey);
return $decrypted;
}
For AES decryption:
public function decryptSecretData($data, $secretKey, $iv)
{
$cipher = "aes-256-cbc";
if (in_array($cipher, openssl_get_cipher_methods()))
{
$iv = hex2bin($iv);
$originalData = openssl_decrypt($data, $cipher, $secretKey, $options=0, $iv);
return $originalData;
}
}
But right now I'm just getting this error:
file: "...\Services\EncryptionService.php"
line: 101
message: "hex2bin(): Input string must be hexadecimal string"
It points to this line inside decryptData():
$binaryData = hex2bin($data);
How do I properly send the data from the client so the server can properly decrypt it?
EDIT:
I'm using these libraries:
https://github.com/travist/jsencrypt
https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js
Content-Typedoes the POST request use? - georgeawgContent-Type, the value istext/html; charset=UTF-8. Data seem to arrive intact. - herondaletext/html. The AngularJS framework normally usesapplication/json. Also the nomenclature in the code is confusing. There is a var namedsecret_keybut thesecret_keyproperty of the sent object is different. It makes the code difficult to understand, debug, test, and maintain. - georgeawg$scope.payment_data.secret_key = secret_key_rsa;The AES secret key has to be encrypted in RSA using the public key from the server so only the server can decrypt it using its private key. (That RSA encryption part on the client side is already included in the question, I already had that part commented.) - herondale