CryptoJS AES in PHP and CryptoJS.AES.decrypt in Nodejs - javascript

I tried to find examples relate to CryptoJS decrypt in PHP but failed with me.
In Nodejs, i use these code for decrypt:
let decrypted = CryptoJS.AES.decrypt(encrypted, key).toString(CryptoJS.enc.Utf8)
How can I decrypt the same as above in PHP ?
This is example for encrypted and key string:
encrypted:
U2FsdGVkX19K5LVvRXaJ9BIIUZexwZLXPbYRSLlN53mXahlwvEtEEPGLnzr9lWF5A97msFXZEg/tjCCv0QNfV/Pv5l6tzMmLXH4TthEDOlu7QDOxB529fDEfkOvBPnBpPXd+SijAUptLhGqEXhPbuPQLYdAwVdjPO+TnH43q6YOT7C9ClR5sf7+RKsVHzG6NdGszB8JUuhpvFYPOigUXQbD/YnAbk3hWn+odgvVIiJSSO0KWodVm7Dczr41nBO2mtJRe7hstSM93t7zwztsmXQ==
key:
0c135f43cff3e8a55a0ddb001f6293c5
Thanks.

Related

About RSA+AES encryption (how to decrypt AES in PHP)

Today I tried to encrypt and transfer the user-submitted password through the RSA+AES method. I have already completed the preparation of the front-end JS (the code is as follows, and the result of the operation is the same, AES, the value of the RSA encryption will be changed), it uses The two libraries, jsencrypt and crypto-js, are now writing PHP for backend decryption (the code is as follows), but I have encountered some difficulties in this process. The RSA decryption part has been written and tested correctly, but I I don't know how to write the AES decryption part. Even though I have consulted a lot of materials, their examples are different from me. I don't know how to use it (I will attach some examples at the end of the article).
problem:
1. Is my JS encryption part correct and logical?
2, how should I write PHP AES decryption part;
3. Is my idea correct? :
Client (JavaScript):
AES encryption original user password
RSA public key encryption AES key
---data transmission---
Server (PHP):
RSA private key decryption Get AES key
AES decryption Get the original user password
Obtain the encrypted user password by encrypting the original user password and store it in the database.
My JavaScript code:
$(function () {
//Encrypted part
//AES
var password_form="QAQ";
console.log(password_form);
var password = CryptoJS.AES.encrypt(password_form,'Lime Website').toString();
console.log(password);
//RSA
var public_key = $("#inputPublic_key").val();
console.log(public_key);
var private_key = $("#inputPrivate_key").val();
console.log(private_key);
var encrypt = new JSEncrypt();
encrypt.setPublicKey(public_key);
var AES_key = encrypt.encrypt(password);
console.log(AES_key);
});
//Decryption part (actually should be done by the server, here for convenience)
//RSA
var decrypt = new JSEncrypt();
decrypt.setPrivateKey(private_key);
var AES_key_decrypt = decrypt.decrypt(AES_key);
console.log(AES_key_decrypt);
//AES
var bytes = CryptoJS.AES.decrypt(AES_key_decrypt,'Lime Website');
var password_decrypt = bytes.toString(CryptoJS.enc.Utf8);
console.log(password_decrypt);
My PHP code:
<?php
$private_key = '-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQ
WMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNR
aY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQAB
AoGAfY9LpnuWK5Bs50UVep5c93SJdUi82u7yMx4iHFMc/Z2hfenfYEzu+57fI4fv
xTQ//5DbzRR/XKb8ulNv6+CHyPF31xk7YOBfkGI8qjLoq06V+FyBfDSwL8KbLyeH
m7KUZnLNQbk8yGLzB3iYKkRHlmUanQGaNMIJziWOkN+N9dECQQD0ONYRNZeuM8zd
8XJTSdcIX4a3gy3GGCJxOzv16XHxD03GW6UNLmfPwenKu+cdrQeaqEixrCejXdAF
z/7+BSMpAkEA8EaSOeP5Xr3ZrbiKzi6TGMwHMvC7HdJxaBJbVRfApFrE0/mPwmP5
rN7QwjrMY+0+AbXcm8mRQyQ1+IGEembsdwJBAN6az8Rv7QnD/YBvi52POIlRSSIM
V7SwWvSK4WSMnGb1ZBbhgdg57DXaspcwHsFV7hByQ5BvMtIduHcT14ECfcECQATe
aTgjFnqE/lQ22Rk0eGaYO80cc643BXVGafNfd9fcvwBMnk0iGX0XRsOozVt5Azil
psLBYuApa66NcVHJpCECQQDTjI2AQhFc1yRnCU/YgDnSpJVm1nASoRUnU8Jfm3Oz
uku7JUXcVpt08DFSceCEX9unCuMcT72rAQlLpdZir876
-----END RSA PRIVATE KEY-----';
$private_key_public_key_availability = openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
$AES_key = "iOks+yhKxQBiqtd5rHQRNdXOGqixhNzquuZuPZ5dDsYfh1nDTLiygukiyexNBqHfmA7zis1nRTZW2Nw4bN5Pr2yCgvh1GPV6K5WigO5jD1+ztuyp1hV5ymNSws6EUPPjW9cwrOpO7EIeiYjvGo7ziyPwsCU0vwtQAkNAFY3uhB0=";
$AES_key_decrypted = "";
echo "After decrypting the data:";
openssl_private_decrypt(base64_decode($AES_key),$AES_key_decrypted,$private_key_public_key_availability);
echo $AES_key_decrypted;
Screenshot of one of the JavaScript running results:
Screenshot
Some examples:
https://odan.github.io/2017/08/10/aes-256-encryption-and-decryption-in-php-and-csharp.html
AES - Crypto JS & PHP
Java encrypt AES, PHP decrypt AES
Finally, sorry for my bad English.

CryptoJS encryption and java side decryption

I am trying to encrypt password with cryptojs and then I will decrypt the encrypted string on server side. I added script
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/aes.js"></script>
var key="abcdef";
var password = document.getElementById('password').value;
var encrypted = CryptoJS.AES.encrypt(password, key);
I am getting error
ReferenceError: CryptoJS is not defined
Can someone tell me how can i do encryption in jsp and decrypt it on java side with key defined on jsp.
Thank you.
I found core library and Now I can encrypt and decrypt on Jsp
var encryptedpassword=CryptoJS.AES.encrypt(password,'abcd');
var ciphertext = encryptedpassword.ciphertext.toString(CryptoJS.enc.Base64);
console.log(ciphertext);
and decrypted using following
var decryptedpassword=CryptoJS.AES.decrypt(encryptedpassword,'abcd');
var plaintext = decryptedpassword.toString(CryptoJS.enc.Utf8);
console.log(plaintext);
My problem now is I want to decrypt the encrypted password on java side can some one tell me how can I do it?

Encrypt the ROR Byte Data in JavaScript JSON array

I am using RoR for server side and sending some encryption data to JS Client side. For ROR I am using OpenSSl encryption technique.
`c= OpenSSL::Cipher::Cipher.new('aes-256-cbc')
c = cipher.encrypt
c.key = Digest::SHA256.digest(key)
Base64.strict_encode64(c.update(value.to_s) + c.final)
`
This is my code for encryption in ROR
`var cipherParams:any = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(encrypted_data)
});
var digest = CryptoJS.SHA256(key.toString(CryptoJS.enc.Utf8));
let bytes = CryptoJS.AES.decrypt(cipherParams, digest, {iv: iv});
bytes.toString(CryptoJS.enc.Utf8);
`
This is my JS decryption logic
when I am encrypting some key value pair data from server I am not able to decrypt it. I am getting this error
MalFormed Utf8
but when I am trying to decrypt single value like: "5678" I am getting correct value.If I changed CryptoJS.enc.Utf8 to CryptoJS.enc.Latin1 I am getting some unreadable value but error is not showing.
I think converting it to UTF8 is giving problem.But why?
I have tried many solutions. I am using proper key and digest and IV, I have checked it multiple times, and I am also sending proper string keys and values.

Laravel 5 - Decrypt Crypt::encrypt in Javascript

I'm using Crypt::encrypt to encrypt my data and feed to Javascript code. How can I decrypt the data in Javascript?
Using laravel 5.1 and CryptoJS which can be found at (https://code.google.com/p/crypto-js/).
in .env set:
APP_KEY=uberkeythatrocks
in config/app.php set:
'cipher' => 'AES-256-CBC'
in MyController.php:
$mySecret = "Something I wanna hide from them";
$encrypted = Crypt::encrypt($mySecret);
in index.js:
var key = "uberkeythatrocks";
var decrypted = CryptoJS.AES.decrypt(encrypted, key);
var readable = decrypted.toString(CryptoJS.enc.Utf8);
IMPORTANT:
The 'key' in PHP must be the same with 'key' in JS and the 'cipher' in PHP must be the same in JS however, CryptoJS will automatically select either AES-128-CBC or AES-256-CBC depending on the length of your 'key'. Although laravel 5.1 default 'cipher' is AES-256-CBC so I would suggest you get your 'key' from .env file to use in JS.
To change or generate a new 'key' from Laravel
C:/mylaravel> php artisan key:generate [enter]
To use AES-128-CBC
Edit config/app.php and set 'cipher' => 'AES-128-CBC'
then
C:/mylaravel> php artisan key:generate [enter]
NOTE that the change of 'key' will mean that an existing user account login password will not work unless you delete the user and then create new.
HOPE THIS HELPS! :)
CryptoJs and Laravel 6 & 7.x
Place a Mix variable inside .env file
MIX_APP_KEY=${APP_KEY}
See: https://laravel.com/docs/7.x/mix#environment-variables
In /resources/assets/js/app.js add:
const CryptoJS = require("crypto-js");
window.decrypt = (encrypted) => {
let key = process.env.MIX_APP_KEY.substr(7);
var encrypted_json = JSON.parse(atob(encrypted));
return CryptoJS.AES.decrypt(encrypted_json.value, CryptoJS.enc.Base64.parse(key), {
iv : CryptoJS.enc.Base64.parse(encrypted_json.iv)
}).toString(CryptoJS.enc.Utf8);
};
And finally somewhere in your script you can decrypt like so:
console.log(decrypt(encrypted_text));
I SOLVE THIS:
I'm using Laravel Framework 5.7.28 and i want to decrypt some users passwords in my node.js application
For Decrypt in my Js file i include CryptoJS and Base64 JS
Here is the code:
$key is the APP_KEY that you have in your .env file
$encrypted is what you encrypt with the Crypt::encrypt in laravel
var CryptoJS = require("crypto-js");
var Base64 = require('js-base64').Base64;
var encrypted = '{{ $encrypted }}';
var key = "{{ $key }}";
var encrypted_json = JSON.parse(Base64.decode(encrypted));
// Now I try to decrypt it.
var decrypted = CryptoJS.AES.decrypt(encrypted_json.value, CryptoJS.enc.Base64.parse(key), {
iv : CryptoJS.enc.Base64.parse(encrypted_json.iv)
});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
The answers above didn't work for me. So I tried to encrypt the string "1234" on Laravel 8 and then decrypt it on Node.js.
My actual use case is that we set our OAuth2 access token as an encrypted cookie on Laravel 8. Then our client sends HTTP-requests to a Node.js backend (microservice architecture). To validate the JWT token, the Node.js backend needs to decrypt the (Laravel)-encrypted access token first.
ENCRYPT (Laravel 8):
Open any Controller and add the following code in a function:
use Illuminate\Support\Facades\Crypt;
return Crypt::encrypt("1234");
If you now open the route, which is linked to the controller method, you get the encrypted string of "1234".
DECRYPT (Node.js)
Please make sure to install crypto-js first (https://github.com/brix/crypto-js).
Do the following steps before you run the code:
Replace "your_string_to_decrypt" by the encrypted "1234" string (you retrieved from Laravel before)
Replace "your_laravel_app_key" with your Laravel APP_KEY from your .env (remove the "base64:" part !)
Important to know: Your encryption cipher-method in Laravel is defined in config/app.php. The default is "AES-256-CBC". Crypto-Js automatically selects the right AES-cipher depending on the length of your specified key. After removing "base64:" your key should have 44 characters for using "AES-256-CBC". (https://security.stackexchange.com/questions/45318/how-long-in-letters-are-encryption-keys-for-aes#:~:text=An%20AES%20128%2Dbit%20key,hexadecimal%20string%20with%2032%20characters.)
CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key.
https://cryptojs.gitbook.io/docs/#ciphers
import CryptoJS from 'crypto-js';
let payload = "your_string_to_decrypt"
let key = "your_laravel_app_key"
let encryptStr = CryptoJS.enc.Base64.parse(payload);
let encryptData = encryptStr.toString(CryptoJS.enc.Utf8);
encryptData = JSON.parse(encryptData);
let iv = CryptoJS.enc.Base64.parse(encryptData.iv);
var decrypted = CryptoJS.AES.decrypt(encryptData.value, CryptoJS.enc.Base64.parse(key), {
iv : iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
decrypted = CryptoJS.enc.Utf8.stringify(decrypted);
console.log(decrypted)
Finally you are done and the Node.js log shows "1234".
(Of course this is not the best code, but it shows the functionality).
References:
Node.js code: https://gist.github.com/huzemin/e8d7a904cec55d4d7635c9322f143c42

Mysql AES_ENCRYPT => client side JavaScript Aes.Ctr.decrypt issue

The case
I have some sensitive data in MySQL DB, and I want to encrypt it when I do a SELECT statement. Then I want to decrypt it on client side with JavaScript.
Here is some example:
MySQL select statement:
SELECT HEX( AES_ENCRYPT( 'text', 'secret' ) )
Result:
CAC9877FC9203920EC4C0E8F1CB5C49C
For client side AES JavaScript decrypt implementation I’ve tried the following libraries: Crypto-js and AES Advanced Encryption Standard.
For Crypto-js I’ve followed the Mysql AES encryption parameters( described here: http://bugs.mysql.com/bug.php?id=16713) to be equal with client-side decryption parameters but it doesn’t work.
With the second library it doesn’t seem to work either.
Example code using Crypto-js:
CryptoJS.AES.decrypt(
'CAC9877FC9203920EC4C0E8F1CB5C49C',
'secret',
{
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.ZeroPadding
}
);
Result:
WordArray.t.extend.init
{
words: Array[8],
sigBytes: 24,
init: function,
toString:function,
concat: function…
}
sigBytes: 24
words: Array[8]
0: -140444473
1: 2005116093
2: -506226828
3: -210568886
4: -277754559
5: 880241217
6: 598097705
7: -2102072885
length: 8
__proto__: Array[0]
__proto__: s
Example of the client-side decrypt implementation with Advanced Encryption Standard library:
Aes.Ctr.decrypt(window.atob('CAC9877FC9203920EC4C0E8F1CB5C49C'), 'secret', 128);
Result: "40^¡®bÞøgÈ"
Aes.Ctr.decrypt('CAC9877FC9203920EC4C0E8F1CB5C49C', 'secret', 128);
Result: "ӽ+) ¾ %[ø\3 "
Could you please tell me what I’m doing wrong?
UPDATE
According to the Thomas comments, I've decided to switch on PHP server side encryption instead of MySQL encryption.
After half a day tries finally I've managed to find a solution and the case i have already works: encrypts a string on server side with PHP and decrypts it on client side with JavaScript using the mentioned CryptoJS library.
Here is an example of the codes:
PHP
<?php
class Encryption
{
public function encrypt($text){
$key = md5("secret");
$iv = utf8_encode("1234567812345678");
return mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$key,
$text,
MCRYPT_MODE_CBC,
$iv);
}
}
JavaScript
function decryptData(text){
var hash = CryptoJS.MD5('secret');
var key = CryptoJS.enc.Utf8.parse(hash);
var iv = CryptoJS.enc.Utf8.parse('1234567812345678');
var dec = CryptoJS.AES.decrypt(
text,
key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
});
return CryptoJS.enc.Utf8.stringify(dec);
}
How to use it
Server side(PHP):
$sensitiveText = "Some sensitive information";
$encString = Encryption::encrypt($sensitiveText);
echo $encString;
Client side(JavaScript):
var decrypted = decryptData('<?=$encString;?>');
Don not forget to load the appropriate CryptoJS libraries: CBC && ZeroPadding
This post help me a lot: http://lalengueta.blogspot.com/2013/07/test-criptografico-php-mcrypt-y.html You can find information for the opposite scenario as well.
The MySQL docs you linked mention that the encryption mode that is used in MySQL is ECB, yet, you're using CTR in your decryption code.
You might want to switch to ECB.
Big, Fat, Warning: Don't use ECB
ECB is a very unsafe encryption mode, you should not use ECB to encrypt any sensitive data.
Consider encrypting in your server-side code, not in MySQL, so as to use a more reliable encryption mode (I'd recommend CBC or CTR for simplicity).

Categories