GitLab Commit is coming up on August 3-4. Learn how to innovate together using GitLab, the DevOps platform. Register for free: gitlabcommitvirtual2021.com

Commit 2fd79c8c authored by vaared's avatar vaared
Browse files

initial commit

parents
Copyright (c) 2018 gitlab.com/vaared
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# upload-vaa, client-side encrypted file host
[https://upload.vaa.red](https://upload.vaa.red)
**upload-vaa** is a client-side encrypted file host. Upload any file you want.\* Image, audio and video files are automatically embedded. Try to upload an image for example!
Since the file is encrypted in the client-side (in user's browser), the contents of the file can't be viewed by the admins of the server. Not even filename or file type.
\* within legal limits of course
## Command-line API
There is a simple bash client available for uploading files: [api-client](api-client/).
## Self-hosting
If you want to self-host, here's a guide how to do it in linux-apache-mysql-php based system: [SELFHOST.md](SELFHOST.md).
## How it works
When user uploads a file, it will be encrypted in the user's browser using [CryptoJS](https://github.com/brix/crypto-js) library before it gets uploaded to the server. When user opens up an encrypted file, it will decrypted in the user's browser using the same CryptoJS library.
CryptoJS defaults to 256 bit key size for AES, PKCS#7 padding and CBC mode. AES has a 128 bit block size which is also the IV size. CryptoJS uses the non-standardized OpenSSL KDF for key derivation (EvpKDF) with MD5 as the hashing algorithm and 1 iteration. Since the MD5 is hard coded into the CryptoJS function used to derive the key from the passphrase, in this project [we are overwriting the default config](https://gitlab.com/vaared/upload.vaa.red/blob/master/src/js/original/crypto.js#L2139) and using SHA-256 instead. In newer versions of OpenSSL, SHA-256 is also used instead of MD5, so this ensures compatibility with the OpenSSL library.
## License
All the code is licensed under MIT.
## Guide to self-host with LAMP installation
**In this guide we are assuming that your site will running on URL: `https://example.com/upload-vaa`.
Change directories and URLs accordingly during the steps.** There's not yet any simple and easy installation file.
### 1. Get all the files
Clone the source repository:
```
git clone https://gitlab.com/vaared/upload.vaa.red.git
```
Copy the `src` files to your www-directory. For example:
```
cp -R upload.vaa.red/src/* /var/www/html/upload-vaa/
```
Also make sure that you have proper file permissions to the wwww-directory (if some command gives permission error, try using `sudo`).
### 2. Create database and tables
```
cd /var/www/html/upload-vaa/
```
Run `setup.sql` to your mysql.
For example: through command line:
```
mysql -u root -p < setup.sql
```
or through phpMyAdmin.
### 3. Apache configurations
For example:
```
sudo nano /etc/apache2/sites-available/000-default-le-ssl.conf
```
Add these configs:
```
<Directory /var/www/html/upload-vaa>
Options -Indexes
</Directory>
RewriteEngine On
RewriteRule ^/upload-vaa/([0-9A-Za-z]+)$ /upload-vaa/index.php?id=$1 [L]
RewriteRule ^/upload-vaa/delete/([0-9A-Za-z]+)$ /upload-vaa/delete/index.php?id=$1 [L]
RewriteRule ^/upload-vaa/upload/file /upload-vaa/uploader.php
```
### 4. Replace default URLs and directories
Make sure you are in your www-directory (`cd /var/www/html/upload-vaa/`).
Edit `WWW_DIR` to your www-directory and run this command on your terminal (**no trailing slash**):
```
WWW_DIR=/var/www/html/upload-vaa
```
And then run this command (again, make sure your current path is your www-directory `cd /var/www/html/upload-vaa/`):
```
find ./ -type f -exec sed -i "s|/var/www/upload|$WWW_DIR|g" {} \;
```
Edit `WWW_URL` to your URL (**no trailing slash or _https://_**):
```
WWW_URL=example.com/upload-vaa
```
And then run this command:
```
find ./ -type f -exec sed -i "s|upload.vaa.red|$WWW_URL|g" {} \;
```
### 5. Generate all the CSS/JS/HTML files
```
sudo npm install -g cssnano \
sudo npm install -g cssnano-cli \
sudo npm install -g npm \
sudo npm install -g html-minifier \
sudo npm install -g uglify-js
```
```
cd js/original
```
```
cat jquery.js crypto.js main.js | uglifyjs --compress --mangle -o app.js
```
```
cat jquery.js crypto.js decrypt.js | uglifyjs --compress --mangle -o app.decrypt.js
```
```
mv app.js app.decrypt.js ../
```
```
cd ../../
```
```
cd css/original
```
```
cssnano main.css main.min.css
```
```
cssnano decrypt.css decrypt.min.css
```
```
mv main.min.css decrypt.min.css ../
```
```
cd ../../
```
```
html-minifier --collapse-whitespace --remove-comments --remove-optional-tags --remove-redundant-attributes --remove-script-type-attributes front_template.html -o front_template_minified.html
```
### 6. Permissions
```
sudo chown -R www-data:www-data ie/
```
```
sudo chown -R www-data:www-data i/
```
```
sudo chown www-data:www-data db.php
```
```
sudo chmod 640 db.php
```
### 7. Database credentials
Edit the file and use your mysql credentials.
```
sudo nano db.php
```
### 8. Automatic file deletion
Edit the `auto_delete.php` and use your mysql credentials, and then place the file outside of your www-directory, for example:
```
sudo mkdir /var/www-inaccessible/
sudo mv auto_delete.php /var/www-inaccessible/
```
```
sudo crontab -e
```
Add this to the end of the file:
```
* * * * * php /var/www-inaccessible/auto_delete.php > /dev/null 2>&1
```
### 9. php.ini configs
Add these configs to your `php.ini` file. For example:
```
sudo nano /etc/php/7.0/apache2/php.ini
```
Find these configs and change them to 50M:
```
upload_max_filesize = 50M
post_max_size = 50M
```
Note: the default max filesize for the encrypted uploads are 30 MB, but because of the client-side encryption, 30 MB files will be about 45-49 MB after encryption. That's why the 50 MB limit. Max filesize isn't yet configurable via any config file, but if you want to change it now you can edit the `uploader.php` and `main.js` files.
### 10. Remove installation files and restart apache
```
rm setup.sql
```
```
sudo service apache2 restart
```
Now the site should be live `https://example.com/upload-vaa`.
# Usage
./upload.sh [file path] [-d, to show deletion url]
```
chmod +x upload.sh
```
```
./upload.sh image.png
```
You can make it to your $PATH, so you could just `upload image.png`, for example:
```
sudo mv upload.sh /usr/bin/upload
```
```
sudo chmod +x /usr/bin/upload
```
#!/bin/bash
if [ -z "$1" ]
then
echo "I need a file! Usage: upload.sh [file path] [-d, to show deletion url]"
exit 1
fi
file_in_base64="$(base64 -w 0 $1)"
file_mime="$(file --mime-type $1 -b)"
base64_string="data:$file_mime;base64,$file_in_base64"
echo $base64_string > $1.b64
enc_password=`tr -dc A-Za-z0-9 < /dev/urandom | head -c 32 | xargs`
openssl enc -aes-256-cbc -e -base64 -in $1.b64 -out $1.enc -pass pass:$enc_password 2> /dev/null
tr -d '\n' < $1.enc > $1.enc.trimmed # OpenSSL -A flag would make the data one line, but the -A flag is "BUGGY". See: https://wiki.openssl.org/index.php/Command_Line_Utilities. Let's do it on our own then.
encrypted_file=`cat $1.enc.trimmed`
json=$(curl -s -F encrypting=true -F "encrypted_base64=<$1.enc.trimmed" https://upload.vaa.red/upload/file)
file_id=`echo $json | jq -r '.fileId'`
deletion_id=`echo $json | jq -r '.deletionId'`
echo "https://upload.vaa.red/$file_id#$enc_password"
if [ ! -z "$2" ]
then
echo "https://upload.vaa.red/delete/$deletion_id"
fi
rm $1.enc $1.enc.trimmed $1.b64
<?php
$servername = "127.0.0.1";
$username = "user";
$password = "defaultmysqlpassword";
$dbname = "uploads";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die();
}
$sql="SELECT id, when_to_delete FROM data";
$result = $conn->query($sql);
$time = new DateTime();
$ids_to_delete = array();
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$delete_date = $row["when_to_delete"];
$id = $row["id"];
if($time > new DateTime($delete_date)) {
if(strpos( $id, '.' ) !== false) {
array_push($ids_to_delete, $id);
unlink('/var/www/upload/i/'.$id.'');
} else {
array_push($ids_to_delete, $id);
unlink('/var/www/upload/ie/'.$id.'.aes');
}
}
}
}
if (!empty($ids_to_delete)) {
$string_ids = "'".implode("','", $ids_to_delete)."'";
$sql = "UPDATE data SET exists_on_the_disk=0 WHERE id IN (".$string_ids.")";
if ($conn->query($sql) !== TRUE) {
die();
}
}
$conn->close();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="theme-color" content="#a20000">
<meta name="msapplication-navbutton-color" content="#a20000">
<meta name="apple-mobile-web-app-status-bar-style" content="#a20000">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex">
<link rel="icon" href="https://vaa.red/fav.png" sizes="96x96">
<title>Upload vaa</title>
<style type="text/css">
/* thanks for the anonymous one who contributed to these styles! https://www.reddit.com/r/uploadvaared/comments/a29m05/a_couple_of_questions/ */
body {
font-family: sans-serif;
background: url(https://upload.vaa.red/css/2gcm2Y.png);
background-size: auto;
}
h1, h2, h3, h4, h5, h6 {
color: #cc6274;
}
.centered {
margin: auto;
width: 1024px;
}
p {
color: #fff;
}
ul {
color: #d7cfd0;
}
a:link,
a:visited {
color: #f34a4a;
}
a:hover,
a:active {
color: #cc6274;
}
@media (max-width:1050px) {
.centered {
width: calc(100% - 30px);
padding-left: 30px;
}
pre {
overflow-x: scroll;
}
}
</style>
</head>
<body>
<div class="centered">
<h1>Contact</h1>
<p>admin@localhost</p>
</div>
</body>
</html>
<!DOCTYPE html><html lang=en><meta charset=utf-8><meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width"><title>Error 500 (Server Error)!!1</title><style>*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{color:#222;text-align:unset;margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px;}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}pre{white-space:pre-wrap;}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}</style><div id="af-error-container"><a href=//www.google.com><span id=logo aria-label=Google></span></a><p><b>500.</b> <ins>That’s an error.</ins><p>There was an error. Please try again later. <ins>That’s all we know.</ins></div>
\ No newline at end of file
<!DOCTYPE html><html lang=en><meta charset=utf-8><meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width"><title>Error 500 (Server Error)!!1</title><style>*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{color:#222;text-align:unset;margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px;}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}pre{white-space:pre-wrap;}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}</style><div id="af-error-container"><a href=//www.google.com><span id=logo aria-label=Google></span></a><p><b>500.</b> <ins>That’s an error.</ins><p>There was an error. Please try again later. <ins>That’s all we know.</ins></div>
\ No newline at end of file
html,
body,
img {
margin: 0;
padding: 0;
background: #0e0e0e;
}
pre {
display: none;
}
a,
h1 {
font-size: 5rem;
text-align: center;
display: block;
font-family: sans-serif;
color: white;
}
p.bl_p {
text-align: center;
color: white;
text-align: center;
font-size: 2rem;
}
h2#c {
color: white;
text-align: center;
font-size: 2.3rem;
}
p.bl_p a {
font-size: 2rem;
text-align: left;
display: inline-block;
}
img,
video,
audio {
left: 50%;
top: 50%;
max-width: 100vw;
max-height: 100vh;
position: absolute;
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
}
div#botton_link {
position: fixed;
bottom: 0;
right: 0;
background: #540606;
border: 1px solid #484747;
margin-bottom: 10px;
margin-right: 10px;
}
div#botton_link:hover {
background: #840000;
}
div#botton_link a {
font-size: 1rem;
text-decoration: none;
padding: 10px;
}
/* noto-sans-tc-regular - latin */
@font-face {
font-family: 'Noto Sans TC';
font-style: normal;
font-weight: 400;
src: url('fonts/noto-sans-tc-v2-latin-regular.eot');
/* IE9 Compat Modes */
src: local('Noto Sans TC Regular'), local('NotoSansTC-Regular'), url('fonts/noto-sans-tc-v2-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('fonts/noto-sans-tc-v2-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
url('fonts/noto-sans-tc-v2-latin-regular.woff') format('woff'), /* Modern Browsers */
url('fonts/noto-sans-tc-v2-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
url('fonts/noto-sans-tc-v2-latin-regular.svg#NotoSansTC') format('svg');
/* Legacy iOS */
}
/* noto-sans-tc-900 - latin */
@font-face {
font-family: 'Noto Sans TC';
font-style: normal;
font-weight: 900;
src: url('fonts/noto-sans-tc-v2-latin-900.eot');
/* IE9 Compat Modes */
src: local('Noto Sans TC Black'), local('NotoSansTC-Black'), url('fonts/noto-sans-tc-v2-latin-900.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('fonts/noto-sans-tc-v2-latin-900.woff2') format('woff2'), /* Super Modern Browsers */
url('fonts/noto-sans-tc-v2-latin-900.woff') format('woff'), /* Modern Browsers */
url('fonts/noto-sans-tc-v2-latin-900.ttf') format('truetype'), /* Safari, Android, iOS */
url('fonts/noto-sans-tc-v2-latin-900.svg#NotoSansTC') format('svg');
/* Legacy iOS */
}
#length_menu,
#deletion_menu,
#metadata_menu {
width: 100%;
float: left;
}
#length_menu span,
#deletion_menu span,
#metadata_menu span {
float: left;
width: 46%;
text-align: right;
}
#length_menu select,
#deletion_menu select,
#metadata_menu select {
width: 45%;
float: left;
margin-left: 25px;
max-width: 320px;
color: black;
}
input#user_password {
float: left;
border: 1px solid #000;
background: #fff;
padding: 6px;
float: left;
margin-left: 3px;
max-width: 320px;
color: #000;
}
#user_deletion_time {
border: 1px solid #000;
background: #fff;
padding: 6px;
float: left;
margin-left: 3px;
max-width: 320px;
color: #000;
}
input#upfile {
display: none;
box-sizing: border-box;
overflow: hidden;
}
label.file-button {
width: 100%;
font-size: 3rem;
margin: 0 auto;
text-align: center;
float: left;
border: 9px solid #2b040c;
background: #d407297d;
color: #e9ebef;
padding-top: 60px;
padding-bottom: 60px;
border-radius: 0px;
transition: background 0.21s;
-moz-transition: background 0.21s infinite;
-webkit-transition: background 0.21s infinite;
border-radius: 0px;
box-sizing: border-box;
overflow: hidden;
background: #d4072954;
}
form {
width: 100%;
float: left;
text-align: center;
padding: 0;
margin: 0;
}
body {
background: url(https://upload.vaa.red/css/2gcm2Y.png);
margin: 0;
padding: 0;
width: 100%;
float: left;
background-size: auto;
font-family: 'Noto Sans TC';
font-style: normal;
font-weight: 400;
}
input[type="submit"] {
width: 100%;
text-align: center;
border-radius: 0px;
float: left;
padding: 0;
margin: 0;
font-size: 4rem;
margin: 0 auto;
text-align: center;
float: left;
color: #e9ebef;
font-family: sans-serif;
padding-top: 39px;
padding-bottom: 33px;
border-radius: 0px;
border: 9px solid #2c0031;
background: #d100ff9e;
transition: background 0.21s;
-moz-transition: background 0.21s infinite;
-webkit-transition: background 0.21s infinite;
animation: border-change 2s;
-moz-animation: border-change 1s infinite;
-webkit-animation: border-change 1s infinite;
}
#encryption_notice {
display: inline-block;
display: none;
font-size: 1rem;
text-align: center;
color: #efcfe9;
padding: 10px;