I'm trying to read from an encfs filesystem with JavaScript but don't get the correct use of it. I use the CryptoJS library.
The .ecnfs6.xml with standard settings and password 123456:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<cfg class_id="0" tracking_level="0" version="20">
<version>20100713</version>
<creator>EncFS 1.7.4</creator>
<cipherAlg class_id="1" tracking_level="0" version="0">
<name>ssl/aes</name>
<major>3</major>
<minor>0</minor>
</cipherAlg>
<nameAlg>
<name>nameio/block</name>
<major>3</major>
<minor>0</minor>
</nameAlg>
<keySize>192</keySize>
<blockSize>1024</blockSize>
<uniqueIV>1</uniqueIV>
<chainedNameIV>1</chainedNameIV>
<externalIVChaining>0</externalIVChaining>
<blockMACBytes>0</blockMACBytes>
<blockMACRandBytes>0</blockMACRandBytes>
<allowHoles>1</allowHoles>
<encodedKeySize>44</encodedKeySize>
<encodedKeyData>
A2MxizkB27kOot67DqX/ftXoAiO0P8ORF4BqbKnbMeHuIusJl5y36Qy8o8w=
</encodedKeyData>
<saltLen>20</saltLen>
<saltData>
z59o4aHs2QaKGdoEMEigtqSkXyw=
</saltData>
<kdfIterations>97742</kdfIterations>
<desiredKDFDuration>500</desiredKDFDuration>
</cfg>
</boost_serialization>
I created a file with name and content "test" and tried to decrypt that wit no success:
var data = "Q75cZB2ok,JdXDqvWh8HbwHI"; // filename
var key = "123456";
var salt = "z59o4aHs2QaKGdoEMEigtqSkXyw=";
data = CryptoJS.enc.Base64.parse(data);
salt = CryptoJS.enc.Base64.parse(salt);
var cipher = CryptoJS.AES.decrypt(data, key, {keySize: 192/32});
The way EncFS works is that it creates a volume key (192 bits according to your config) and encrypts the volume key using another key which is derived from the user's password (the algorithm used for deriving the password key is called PBKDF2 - Password-Based Key Derivation Function).
Given that config file, what you have to do is:
Take the user's password, input into PBKDF2 computation along with the salt and iteration count (both present in the config file) to get back the password key.
Using the password key, decrypt the volume key (AES stream decryption) from the encodedKeyData field of the config
Once you have the volume key you can use it to decrypt filenames as well as file contents.
For examples of how this is done, you can take a look at the following library which I wrote in Java:
https://github.com/mrpdaemon/encfs-java
Current JavaScript implementations are far too slow to generate a
PBKDF2 with more than 1000 - 2000 (not noticeably delayed) to
10000 (noticeable delay) iterations. An iteration count like in your
example 97742 would take hours to finish...
Update: Only when using CryptoJS apparently: see JSPerf and JSFiddle for PBKDF2.
Related
I have written an input form (in ServiceNow) for admins to request a new certificate via a Cert Authority integration. However prior to submission i want to validate the Certificate Signing request has the correct headers and a keylength of 2048.
Example of CSR:
-----BEGIN CERTIFICATE REQUEST-----
MIICpTCCAY0CAQAwYDEqMCgGCSqGSIb3DQEJARYbamFtZXN0b21saW5zb25AbmJu
Y28uY29tLmF1MSUwIwYDVQQDDBxTZXJ2aWNlTm93LlRlc3QuSnVseTIxLkxvY2Fs
MQswCQYDVQQGEwJBVTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKpd
VbZG3Ph+UdiOYh+zFqH6pIavANGytWcvEnloG/DboW+JxpWQBqmZqvOZgWnPyC06
wS4f/YpElLFX83/+jLc6Gt3B/QDgfxhGaVnurDx56RvTM1LQVfBZJ3l+OYUmAof+
YB25aRhKQ4krWvXGMUujoi5QSl9yNZlAIzgpjgJ7cRHcbUhlOdcQVz/WnC2dcWB3
H/vLPIzciODOrzwIq1lSJ3OkdOJJ23Ifu19e9ySJsWYoC28THm6Ub8Z9gHHlPTfO
im5UxZFBZjLkx/YphQNNqcMxFMCO/CDo1bZlggws61O2liPzC8LpGwkroYIxngoQ
5rbvm/uyG/HelAFZYT0CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCouy3b62xV
Bu4Scd38HMgtaTCHOndutsuwNnYF6SpxdSTYYMVQIa+gHy3N4vpQ+lNboPlOhsQd
58Jt9iwnmYCR32d36FVmsIpu5xAwweQUBK5v/GIPx5yjY0k8bTFC3vJUsIxbClwC
UtUE5p7p+Ulm+4olk/+VYeKtvE+l+e89NQ4sBlOE5JVSulRsxLjRfQscvj/0Ln/7
7iZQxfgL/Vv1UUBiLfTEmfSyu5i7IomoAUBSJ9xipbh5OWolqHzIBmpQY504Es3X
Ojs9d6KwyCSu5S2yUoj98C+OidqkHXDSfwWQSCfWn1vCuTFQlFS5viYK2pzIjozE
71owCWT8RpGd
-----END CERTIFICATE REQUEST-----
I plan to write a quick client side script to validate the input, but i'm a little stumped on the syntax. Any help appreciated.
This will be very difficult to do up...
Checking the CSR headers is relatively straight forward... you can do something like the following in an onSubmit script
var totalString = g_form.getValue('fieldName').trim();
var headerString = totalString.slice(0, 35);
var encodedCertString = totalString.substring(35, totalString.length - 33);
var footerString = totalString.slice(totalString.length - 33);
var validCert = true;
validCert &= (headerString == '-----BEGIN CERTIFICATE REQUEST-----');
validCert &= (footerString == '-----END CERTIFICATE REQUEST-----');
if(!validCert){
g_form.addErrorMessage('CSR in field missing correct headers');
return false;
}
Where things get "interesting" is that what is between the headers and footer of the CSR is a Base64 encoded PKCS10 binary block of data. Writing a function to deal with binary data is generally beyond what you will want to do in a client side function... the public key itself is merely a portion of that PCKS10 binary package.. not the whole.. so there is no easy way to "decode" it to iterate through the raw binary bites to find the actual key and measure its bit length. Have a look at the PCKS10 binary package format here: https://en.wikipedia.org/wiki/Certificate_signing_request
Most folks that have online CSR decoders actually pass the input to OpenSSL and have it parse the request and report on all of the data that makes it up... For instance: https://redkestrel.co.uk/products/decoder/. You could do something similar but doing so would require a hackish/creative use of a custom MID Server script that you could call using a custom probe... Again.. not something that you would want to mess with within the bounds of a ServiceNow client script.
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.
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
My team must share data between a localnet html/js app, and a server in the same net listening on a websocket.
The first idea was to simply send variables to the server with get
http://192.168.1.100:8080/var=hello
It's simple and works, but we must add a security level to the data exchange, encrypting all in Aes and then hexing the result to send it as plain string.
The best solution that we found is Crypto-JS https://code.google.com/p/crypto-js/
We are able to follow the examples and encrypting/decrypting data inside the same js block, but are unable to decrypt the data on another software.
we do:
var text = "Message";
var password = "Secret Passphrase";
var encrypted = CryptoJS.AES.encrypt(text, password);
var EnText = encrypted.ciphertext; //returns the hexed/encrypted text
var Key = encrypted.key;
It doesn't work with the c# code running on the server, so we tried an online decrypting tool http://aes.online-domain-tools.com/ passing both the password and the Key, but similarly returns unreadable text
JS generated value for reference
EnText: 5768c9b4d75e0cc32b610d9e6f518c36
Key: 005e316192f5162f7fd104ce2c9fe91de6c6f2977849dcd5878226022a7073be
What are we missing?
Ok i got it, the text is in hexadecimal.
Try decyphering it there:
http://www.unit-conversion.info/texttools/hexadecimal/
I've searched for this, there are lots of hits, but I can't find one that is neither complete (pulls all the bits together) nor says its a bad idea, use HTTP. I've tried lots of things based on the hits I've found, but I can't get it to work.
The target problem is to AES encrypt textual data at one place, send it to a web API where it is stored in a database, then retrieve from the database via another API and decode it in the browser. This is not for security in transmission, it is so that, if the originator and the receiver know the key and IV, then it can be stored without the server knowing what the real content is.
The originator code is python, and the web API is python, so to make life easier initially, I'm storing the content unencrypted in the database. I've done AES encrypt/decrypt in python before, so that's not an issue. What I'm trying to do is encrypt in python as the content comes out of the database, transmit it, then decrypt in javascript. I've been using the python 'from Crypto.Cipher import AES' code, and javascript CryptoJS implementation from code.google.com
I'm happy at this stage to write the key and the IV into the code, distribution isn't really a problem as the originator and the client browser are effectively the same system.
I've not added any code because I think it would be more trouble than its worth at this stage.
Thanks in advance!
OK, some code. On the server python(3) side:
text = 'This is a message'
key = 'This is a key123'
iv = 'This is an IV456'
text += (16 - len(text) % 16) * ' ' # Pad to 16 chars, spaces are OK here
aes = AES.new(key, AES.MODE_CBC, iv)
enc = base64.b64encode(aes.encrypt(text)).decode()
print(enc)
enc is passed along with other data, JSON encoded, as the response to an AJAX request. On the client javascript side:
enc = /* from JSON */ ;
console.log(enc) ;
key = 'This is a key123';
iv = 'This is an IV456';
text = CryptoJS.AES.decrypt(Base64.decode(enc), key,
{ iv: iv, mode: CryptoJS.mode.CBC })) ;
console.log(text)
The python print(enc) and the javascript console.log(env) are the same, so I know the b64'd encoded data is coming over OK. The console.log(text) (in Chrome) shows as
l.WordArray.t.extend.init { ... }'
and not 'This is a message'. So why not!
Solved, but another mystery
I used the code from this gist:
https://gist.github.com/andres-erbsen/1307675
But: this uses code from http://crypto-js.googlecode.com/files/... which is not what you get from the download at https://code.google.com/p/crypto-js/downloads/list. The gist code uses Crypto.xxxx names; the download code uses CryptoJS.xxxx names. The gist is 2 years old, has CryptoJS replaced Crypto maybe?