Skip to content

Commit 9a76bd5

Browse files
committed
Add support for AES GSM and other AEAD cipher modes.
1 parent 183be7c commit 9a76bd5

File tree

3 files changed

+57
-42
lines changed

3 files changed

+57
-42
lines changed

backend/res/DataStorage.php

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ class DataStorage
1212
* Set the current views and max views for a specified file.
1313
* When the current views are equal or exceeds max views the file will be deleted and the user will get a 404 error.
1414
*
15-
* @since 2.0
16-
* @global array $conf Configuration variables.
17-
* @global object $mysql_connection MySQL connection.
1815
* @param string $maxViews The new maximum amount of views to set on a file.
1916
* @param string $newViews The new current views to set on a file.
2017
* @return boolean Returns TRUE if the change was successful, otherwise FALSE.
18+
* @since 2.0
19+
* @global array $conf Configuration variables.
20+
* @global object $mysql_connection MySQL connection.
2121
*/
2222
public static function setViews(string $maxViews, string $newViews, File $file, string $password) {
2323
global $conf;
@@ -37,11 +37,11 @@ public static function setViews(string $maxViews, string $newViews, File $file,
3737
/**
3838
* Delete a specific file.
3939
*
40-
* @since 2.0
41-
* @global array $conf Configuration variables.
42-
* @global object $mysql_connection MySQL connection.
4340
* @param string $id The ID for the file.
4441
* @return boolean Returns TRUE if the deletion was successful, otherwise FALSE.
42+
* @global object $mysql_connection MySQL connection.
43+
* @since 2.0
44+
* @global array $conf Configuration variables.
4545
*/
4646
public static function deleteFile(string $id) {
4747
global $conf;
@@ -56,8 +56,8 @@ public static function deleteFile(string $id) {
5656
/**
5757
* Delete all files older than 1 day.
5858
*
59-
* @since 2.1
6059
* @return boolean Returns TRUE if the query was successful, otherwise FALSE.
60+
* @since 2.1
6161
*/
6262
public static function deleteOldFiles() {
6363
global $conf;
@@ -71,12 +71,13 @@ public static function deleteOldFiles() {
7171
/**
7272
* Get the metadata and content of a file.
7373
*
74-
* @since 2.0
75-
* @global array $conf Configuration variables.
76-
* @global object $mysql_connection MySQL connection.
7774
* @param string $id The ID for the file.
7875
* @param string $password Description
7976
* @return mixed Returns the downloaded and decrypted file (object) if successfully downloaded and decrypted, otherwise NULL (boolean).
77+
* @since 2.0
78+
* @since 2.3 Add support for AEAD cipher modes.
79+
* @global array $conf Configuration variables.
80+
* @global object $mysql_connection MySQL connection.
8081
*/
8182
public static function getFile(string $id, string $password) {
8283
global $conf;
@@ -96,7 +97,7 @@ public static function getFile(string $id, string $password) {
9697
$file->setIV($iv);
9798

9899
if ($enc_content !== NULL) {
99-
$metadata_string = Encryption::decrypt(base64_decode($enc_filedata), $password, $iv[1]);
100+
$metadata_string = Encryption::decrypt(base64_decode($enc_filedata), $password, $iv[2], $iv[3]);
100101

101102
/** @var array $metadata_array
102103
* Array containing the following: [name, size, type, deletionPassword, views_array[ 0 => currentViews, 1 => maxViews]]
@@ -107,7 +108,7 @@ public static function getFile(string $id, string $password) {
107108

108109
$file->setDeletionPassword(base64_decode($metadata_array[3]));
109110
$file->setMetaData($metadata);
110-
$file->setContent(Encryption::decrypt(base64_decode($enc_content), $password, $iv[0]));
111+
$file->setContent(Encryption::decrypt(base64_decode($enc_content), $password, $iv[0], $iv[1]));
111112
$file->setMaxViews((int)$views_array[1]);
112113
$file->setCurrentViews((int)$views_array[0]);
113114

@@ -119,20 +120,21 @@ public static function getFile(string $id, string $password) {
119120
/**
120121
* Upload a file to the database.
121122
*
122-
* @since 2.0
123-
* @since 2.2 Removed $enc_content, $iv, $enc_filedata & $maxviews from input parameters. Changed output from $id (string) to $file (object).
124-
* @global array $conf Configuration variables.
125-
* @global object $mysql_connection MySQL connection.
126123
* @param File $file File to upload.
127124
* @param string $password Password to encrypt the file content and metadata with.
128125
* @return boolean Returns TRUE if the action was successfully executed, otherwise FALSE.
126+
* @global object $mysql_connection MySQL connection.
127+
* @since 2.0
128+
* @since 2.2 Removed $enc_content, $iv, $enc_filedata & $maxviews from input parameters. Changed output from $id (string) to $file (object).
129+
* @since 2.3 AAdd support for AEAD cipher modes.
130+
* @global array $conf Configuration variables.
129131
*/
130132
public static function uploadFile(File $file, string $password) {
131133
global $conf;
132134
global $mysql_connection;
133-
$iv = ['content' => Encryption::getIV(), 'metadata' => Encryption::getIV()];
134-
$enc_filecontent = Encryption::encryptFileContent($file->getContent(), $password, $iv['content']);
135-
$enc_filemetadata = Encryption::encryptFileDetails($file->getMetaData(), $file->getDeletionPassword(), 0, $file->getMaxViews(), $password, $iv['metadata']);
135+
$fileContent = Encryption::encryptFileContent($file->getContent(), $password);
136+
$fileMetadata = Encryption::encryptFileDetails($file->getMetaData(), $file->getDeletionPassword(), 0, $file->getMaxViews(), $password);
137+
$iv = [$fileContent['iv'], $fileContent['tag'], $fileMetadata['iv'], $fileMetadata['tag']];
136138
$enc_iv = base64_encode(implode(',', $iv));
137139
$null = NULL;
138140

@@ -143,12 +145,12 @@ public static function uploadFile(File $file, string $password) {
143145

144146
$id = $file->getID();
145147

146-
$bp = $query->bind_param("sssb", $id, $enc_iv, $enc_filemetadata, $null);
148+
$bp = $query->bind_param("sssb", $id, $enc_iv, $fileMetadata['data'], $null);
147149
if (!$bp)
148150
throw new Exception('bind_param() failed: ' . htmlspecialchars($query->error));
149151

150152
// Replace $null with content blob
151-
if (!$query->send_long_data(3, $enc_filecontent))
153+
if (!$query->send_long_data(3, $fileContent['data']))
152154
throw new Exception('bind_param() failed: ' . htmlspecialchars($query->error));
153155

154156
if (!$query->execute())

backend/res/Encryption.php

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,39 @@ class Encryption
1111
/**
1212
* Decrypts data.
1313
*
14-
* @since 2.0
15-
* @global array $conf Configuration variables.
1614
* @param string $data Data to decrypt.
1715
* @param string $password Password used to decrypt.
1816
* @param string $iv IV for decryption.
17+
* @param string $tag
1918
* @return string Returns decrypted data.
19+
* @since 2.0
20+
* @since 2.3 Added support for AEAD cipher modes.
21+
* @global array $conf Configuration variables.
2022
*/
21-
public static function decrypt(string $data, string $password, string $iv) {
23+
public static function decrypt(string $data, string $password, string $iv, string $tag = NULL) {
2224
global $conf;
23-
return openssl_decrypt($data, $conf['Encryption-Method'], $password, OPENSSL_RAW_DATA, $iv);
25+
return openssl_decrypt($data, $conf['Encryption-Method'], $password, OPENSSL_RAW_DATA, $iv, $tag);
2426
}
2527

2628
/**
2729
* Encrypts and encodes the metadata (details) of a file.
2830
*
29-
* @since 2.0
30-
* @since 2.2 Added $deletionpass to the array of things to encrypt.
3131
* @param array $file the $_FILES[] array to use.
3232
* @param string $deletionpass Deletion password to encrypt along with the metadata.
3333
* @param int $currentViews Current views of the file.
3434
* @param int $maxViews Max allowable views of the file before deletion.
3535
* @param string $password Password used to encrypt the data.
36-
* @param string $iv IV used to encrypt the data.
37-
* @return string Returns encrypted file metadata encoded with base64.
36+
* @return array Returns encrypted file metadata encoded with base64.
37+
* @since 2.0
38+
* @since 2.2 Added $deletionpass to the array of things to encrypt.
39+
* @since 2.3 Added support for AEAD cipher modes.
3840
* @global array $conf Configuration variables.
3941
*/
40-
public static function encryptFileDetails(array $file, string $deletionpass, int $currentViews, $maxViews, string $password, string $iv) {
42+
public static function encryptFileDetails(array $file, string $deletionpass, int $currentViews, $maxViews, string $password) {
4143
global $conf;
44+
$cipher = $conf['Encryption-Method'];
45+
$iv = self::getIV($cipher);
46+
4247
$deletionpass = password_hash($deletionpass, PASSWORD_BCRYPT);
4348
$views_string = implode(' ', [$currentViews, $maxViews]);
4449
$data_array = [
@@ -49,34 +54,42 @@ public static function encryptFileDetails(array $file, string $deletionpass, int
4954
base64_encode($views_string)
5055
];
5156
$data_string = implode(" ", $data_array);
52-
$data_enc = openssl_encrypt($data_string, $conf['Encryption-Method'], $password, OPENSSL_RAW_DATA, $iv);
53-
return base64_encode($data_enc);
57+
58+
$data_enc = base64_encode(openssl_encrypt($data_string, $cipher, $password, OPENSSL_RAW_DATA, $iv, $tag));
59+
return ['data' => $data_enc, 'iv' => $iv, 'tag' => $tag];
5460
}
5561

5662
/**
5763
* Encrypts and encodes the content (data) of a file.
5864
*
59-
* @since 2.0
60-
* @global array $conf Configuration variables.
6165
* @param string $content Data to encrypt.
6266
* @param string $password Password used to encrypt data.
63-
* @param string $iv IV used to encrypt data.
64-
* @return string Returns encoded and encrypted file content.
67+
* @return array Returns encoded and encrypted file content.
68+
* @since 2.0
69+
* @since 2.3 Added support for AEAD cipher modes.
70+
* @global array $conf Configuration variables.
6571
*/
66-
public static function encryptFileContent(string $content, string $password, string $iv) {
72+
public static function encryptFileContent(string $content, string $password) {
6773
global $conf;
68-
return base64_encode(openssl_encrypt($content, $conf['Encryption-Method'], $password, OPENSSL_RAW_DATA, $iv));
74+
$cipher = $conf['Encryption-Method'];
75+
$iv = self::getIV($cipher);
76+
77+
$data = base64_encode(openssl_encrypt($content, $cipher, $password, OPENSSL_RAW_DATA, $iv, $tag));
78+
return ['data' => $data, 'iv' => $iv, 'tag' => $tag];
6979
}
7080

7181
/**
7282
* Create an IV (Initialization Vector) string.
7383
* IV contains of random data from a "random" source. In this case the source is OPENSSL.
7484
*
75-
* @since 2.0
85+
* @param string $cipher Encryption method to use.
7686
* @return string Returns an IV string encoded with base64.
87+
* @since 2.0
88+
* @since 2.3 Added support for variable IV length.
7789
*/
78-
public static function getIV() {
79-
return mb_strcut(base64_encode(openssl_random_pseudo_bytes(16)), 0, 16);
90+
public static function getIV(string $cipher) {
91+
$ivLength = openssl_cipher_iv_length($cipher);
92+
return mb_strcut(base64_encode(openssl_random_pseudo_bytes($ivLength)), 0, $ivLength);
8093
}
8194

8295
}

backend/res/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@
2020
#'mysql-table' => 'files',
2121
'mysql-table' => getenv('rb421p9wniz81ttj7bdgrg0ub'),
2222
# Encryption algorithm to use for encrypting uploads.
23-
'Encryption-Method' => 'AES-256-CBC'
23+
'Encryption-Method' => 'aes-256-gcm'
2424
);

0 commit comments

Comments
 (0)