Skip to content
This repository has been archived by the owner on Mar 16, 2023. It is now read-only.

Commit

Permalink
GnuPG PECL package support publication on github
Browse files Browse the repository at this point in the history
  • Loading branch information
yahesh committed Sep 11, 2016
1 parent 4d96af0 commit d1a55ec
Show file tree
Hide file tree
Showing 14 changed files with 370 additions and 183 deletions.
29 changes: 28 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
# 0.8b0 (2016-09-11)

* version bump for GnuPG PECL package support publication on github
* **Beware:** With version 0.8b0 the structure of the secret sharing links has slightly changed. You have to set the *SUPPORT_LEGACY_LINKS* configuration value to *true* if you want to support secret sharing links that have been generated for older versions of Shared-Secrets. Failure to do so will break these legacy links.

# 0.7b2 (2016-09-10)

* rewrote non-PECL encryption to not use ASCII-armoring anymore
* enhanced non-PECL link generation so that PECL and non-PECL links look the same
* cleaned up PECL and non-PECL encryption/decryption code
* simplified and fixed code for PECL or non-PECL call selection
* introduced new configuration variable SUPPORT_LEGACY_LINKS
* introduced code that provides backward-compatibility for legacy links
* tested PECL implementation in chroot environment and failed
* updated readme to reflect observations made in chroot environment

# 0.7b1 (2016-09-08)

* implemented support for the newly released GnuPG PECL version 1.4.0
* introduced homedir support for non-PECL encryption and decryption
* introduced new configuration variable GPG_HOME_DIR
* implemented handling of equation signs for the URL-safe Base64 encoding and decoding
* tested backward-compatibility so that non-PECL URL don't break
* updated howto website which automatically adjusts when PECL is active
* updated readme to decribe how to install the GnuPG PECL
* fixed some typos in the documentation and in comments

# 0.7b0 (2016-09-08)

* version bump for url-safe Base64 encoding publication on github
Expand All @@ -7,7 +34,7 @@
* implemented so-called url-safe Base64 encoding of secrets to reduce URL-encoding junk
* checked backward-compatibility with previous standard URL-encoded URLs
* improved line-break handling in GPG message unstripping
* tested url-safe Base64 encoding feature within chroot environment
* tested URL-safe Base64 encoding feature within chroot environment

# 0.6b0 (2016-09-02)

Expand Down
37 changes: 34 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ To retrieve the secret, simply open the secret sharing link and press the "Read

### Requirements

Shared-Secrets is based on MariaDB 10.0, Nginx 1.10 and PHP 7.0, but should also work with MySQL, Apache and earlier versions of PHP.
Shared-Secrets is based on MariaDB 10.0, Nginx 1.10 and PHP 7.0, but should also work with MySQL, Apache and earlier versions of PHP. GPG encryption is supported through the [GnuPG PECL package](https://pecl.php.net/package/gnupg) as well as through directly calling the gpg binary. Using the GnuPG PECL package is the prefered mechanism due to its cleaner interface. If you want to use the GnuPG PECL package support of the Shared-Secrets service in a chroot environment you have to set up your chroot environment properly - this does not seem to be easy.

### Nginx Setup

Expand Down Expand Up @@ -93,10 +93,39 @@ sudo -u www-data -H gpg --import ./private.asc
sudo -u www-data -H gpg --import ./public.asc
```

### PHP Setup

To use the [GnuPG PECL package](https://pecl.php.net/package/gnupg) it has to be installed and activated on the server. The following steps are based on Ubuntu 16.04 LTS and only serve as an example for the installation and activation of the GnuPG PECL package:
```
# install PHP PEAR/PECL
sudo apt-get install php-pear
# install the PHP development tools
sudo apt-get install php7.0-dev
# install the GPGME development package, see https://www.gnupg.org/related_software/gpgme/index.html
sudo apt-get install libgpgme11-dev
# install the GnuPG PECL package
sudo pecl install gnupg
# register tje GnuPG PECL package as an available module
sudo sh -c 'echo "extension=gnupg.so" > /etc/php/7.0/mods-available/gnupg.ini'
# activate the GnuPG PECL package in PHP CLI and PHP-FPM
sudo ln -s /etc/php/7.0/mods-available/gnupg.ini /etc/php/7.0/cli/conf.d/20-gnupg.ini
sudo ln -s /etc/php/7.0/mods-available/gnupg.ini /etc/php/7.0/fpm/conf.d/20-gnupg.ini
# restart PHP-FPM to load the GnuPG PECL package
sudo /etc/init.d/php7.0-fpm restart
```

### Service Setup

Rename the "config.php.default" to "config.php" and set the necessary configuration items.

**Beware:** With version 0.8b0 the structure of the secret sharing links has slightly changed. You have to set the *SUPPORT_LEGACY_LINKS* configuration value to *true* if you want to support secret sharing links that have been generated for older versions of Shared-Secrets. Failure to do so will break these legacy links.

### TLS Recommendation

It is strongly recommended to use TLS to protect the connection between the server and the clients.
Expand All @@ -105,16 +134,18 @@ It is strongly recommended to use TLS to protect the connection between the serv

* [asmCrypto](https://github.com/vibornoff/asmcrypto.js): for providing PBKDF2 and AES functions
* [Bootstrap](https://getbootstrap.com): for providing an easy-to-use framework to build nice-looking applications
* [buffer](https://github.com/feross/buffer): for providing Base64-encoding and array-conversion functions
* [buffer](https://github.com/feross/buffer): for providing Base64 encoding and array conversion functions
* [clipboard.js](https://clipboardjs.com): for simplifying the copy-to-clipboard use-case a lot
* [GnuPG](https://www.gnupg.org): for providing a reliable tool for secure communication
* [GnuPG PECL package](https://pecl.php.net/package/gnupg): for providing a clean interface to GnuPG
* [html5shiv](https://github.com/aFarkas/html5shiv): for handling Internet Explorer compatibility stuff
* [jQuery](https://jquery.com): for just existing
* [Katharina Franz](https://www.katharinafranz.com): for suggesting Bootstrap as an easy-to-use framework to build nice-looking applications
* [Respond.js](https://github.com/scottjehl/Respond): for handling even more Internet Explorer compatibility stuff

## ToDo

* switch to the [GnuPG PECL](https://pecl.php.net/package/gnupg) once the PHP 7 support is stable
* make PECL method work in a chroot environment to get rid of the direct call method
* switch to a more personalized design (current design is taken from [here](https://github.com/twbs/bootstrap/tree/master/docs/examples/starter-template))
* implement an expiry date functionality

Expand Down
88 changes: 58 additions & 30 deletions actions/read.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
function read_secret($secret) {
$result = null;

# only execute the legacy code if it are activated
if (SUPPORT_LEGACY_LINKS) {
$is_legacy_link = (false !== strpos(rtrim($secret, BASE64_MARKER_END), BASE64_MARKER_END));

# handle secret decoding
if ($is_legacy_link) {
$secret = url_base64_decode_legacy($secret);
} else {
$secret = url_base64_decode($secret);
}
} else {
# handle secret decoding
$secret = url_base64_decode($secret);
}

# get the checksum of the URI content
$checksum = hash("sha256", $secret);

Expand All @@ -32,44 +47,57 @@ function read_secret($secret) {

# only proceed if the fingerprint has not been found
if (0 === $fingerprint_found) {
# get unstripped secret
$unstripped_secret = unstrip_message($secret);

if (null !== $unstripped_secret) {
# only execute the legacy code if it are activated
if (SUPPORT_LEGACY_LINKS) {
# decrypt secret
$decrypted_secret = decrypt($unstripped_secret, GPG_PASSPHRASE_FILE);

if (null !== $decrypted_secret) {
# prepare the write statement
$insert = mysqli_prepare($mysql, MYSQL_WRITE);

if (false !== $insert) {
# only set temporarily
$client_ip = CLIENT_IP;

# set string parameter of write statement to $checksum and client IP
if (mysqli_stmt_bind_param($insert, "ss", $checksum, $client_ip)) {
# execute statement
if (mysqli_stmt_execute($insert)) {
# return secret
$result = htmlentities($decrypted_secret);

# close insert statement before proceeding
mysqli_stmt_close($insert);
$insert = null;
}
}
if ($is_legacy_link) {
$decrypted_secret = decrypt_legacy($secret, GPG_HOME_DIR, GPG_PASSPHRASE_FILE);
} else {
if (GNUPG_PECL) {
$decrypted_secret = decrypt_pecl(base64_decode($secret), GPG_KEY_FINGERPRINT, GPG_HOME_DIR, GPG_PASSPHRASE_FILE);
} else {
$decrypted_secret = decrypt(base64_decode($secret), GPG_HOME_DIR, GPG_PASSPHRASE_FILE);
}
}
} else {
# decrypt secret
if (GNUPG_PECL) {
$decrypted_secret = decrypt_pecl(base64_decode($secret), GPG_KEY_FINGERPRINT, GPG_HOME_DIR, GPG_PASSPHRASE_FILE);
} else {
$decrypted_secret = decrypt(base64_decode($secret), GPG_HOME_DIR, GPG_PASSPHRASE_FILE);
}
}

if (null !== $decrypted_secret) {
# prepare the write statement
$insert = mysqli_prepare($mysql, MYSQL_WRITE);

if (false !== $insert) {
# only set temporarily
$client_ip = CLIENT_IP;

# close insert statement
if (null !== $insert) {
# set string parameter of write statement to $checksum and client IP
if (mysqli_stmt_bind_param($insert, "ss", $checksum, $client_ip)) {
# execute statement
if (mysqli_stmt_execute($insert)) {
# return secret
$result = htmlentities($decrypted_secret);

# close insert statement before proceeding
mysqli_stmt_close($insert);
$insert = null;
}
}

# close insert statement
if (null !== $insert) {
mysqli_stmt_close($insert);
}
}
}
} else {
$result = "<strong>ERROR: SECRET HAS ALREADY BEEN RETRIEVED.</strong>";
}
} else {
$result = "<strong>ERROR: SECRET HAS ALREADY BEEN RETRIEVED.</strong>";
}
}
}
Expand Down
15 changes: 7 additions & 8 deletions actions/share.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ function share_secret($secret) {
if (!empty($secret)) {
# only proceed when the secret is not too long
if (MAX_PARAM_SIZE >= strlen($secret)) {
$encrypted_secret = encrypt($secret, GPG_KEY_FINGERPRINT);
if (GNUPG_PECL) {
$encrypted_secret = encrypt_pecl($secret, GPG_KEY_FINGERPRINT, GPG_HOME_DIR);
} else {
$encrypted_secret = encrypt($secret, GPG_KEY_FINGERPRINT, GPG_HOME_DIR);
}

if (null !== $encrypted_secret) {
# remove everything from encrypted secret that is not necessary
$stripped_secret = strip_message($encrypted_secret);

if (null !== $stripped_secret) {
# return the secret sharing URL
$result = htmlentities(SECRET_SHARING_URL.urlencode(url_base64_encode($stripped_secret)));
}
# return the secret sharing URL
$result = htmlentities(SECRET_SHARING_URL.urlencode(url_base64_encode(base64_encode($encrypted_secret))));
}
} else {
$result = "<strong>ERROR: THE SECRET MUST BE SMALLER THAN ".MAX_PARAM_SIZE." CHARACTERS.</strong>";
Expand Down
9 changes: 9 additions & 0 deletions config.php.default
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
# in the GPG keyring
define("GPG_KEY_FINGERPRINT", "<SET THE GPG KEY FINGERPRINT!!!>");

# this is the GPG home dir that contains the GPG keyring,
# this has to be set in order for the GnuPG PECL to be used
define("GPG_HOME_DIR", null);

# this is the file that contains the passphrase for the
# GPG private encryption key, the file should only contain
# a single line with the passphrase
Expand Down Expand Up @@ -49,4 +53,9 @@
# IP addresses
define("LOG_IP_ADDRESS", true);

# this is the configuration to either enable or disable the
# support for legacy links, set this configuration value to
# true to enable the support for legacy links
define("SUPPORT_LEGACY_LINKS", false);

?>
20 changes: 9 additions & 11 deletions index.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

# Shared-Secrets v0.7b0
# Shared-Secrets v0.8b0
#
# Copyright (c) 2016, SysEleven GmbH
# All rights reserved.
Expand All @@ -24,15 +24,15 @@
# so that is does not change between script files
define("ROOT_DIR", __DIR__);

# include required configuration
require_once(ROOT_DIR."/config.php");

# include required defines
require_once(ROOT_DIR."/libs/shared-secrets.def.php");

# include required execution functions
require_once(ROOT_DIR."/libs/shared-secrets.exec.php");

# include required configuration
require_once(ROOT_DIR."/config.php");

# set default timezone because PHP dislikes to use system defaults
date_default_timezone_set(DEFAULT_TIMEZONE);

Expand All @@ -55,20 +55,15 @@
}
define("SECRET_PARAM", $param);

# prepare uri
# prepare URI
$uri = $_SERVER["REQUEST_URI"];
if (0 === stripos($uri, "/")) {
$uri = substr($uri, 1);
}
# handle URL-encoded URIs
# handle URL encoded URIs
if (false !== strpos($uri, URL_ENCODE_MARKER)) {
$uri = urldecode($uri);
}
# handle URL-Base64-encoded URIs
if ((false !== strpos($uri, URL_BASE64_MARKER_A)) ||
(false !== strpos($uri, URL_BASE64_MARKER_B))) {
$uri = url_base64_decode($uri);
}
define("SECRET_URI", $uri);

# prepare action name, show read page by default
Expand All @@ -84,6 +79,9 @@
}
define("SECRET_ACTION", $action);

# check if the GnuPG PECL package is available
define("GNUPG_PECL", (extension_loaded("gnupg") && is_dir(GPG_HOME_DIR)));

# only proceed when a GET or POST request is encountered
if (in_array(REQUEST_METHOD, array("get", "post"))) {
# import actions based on action name
Expand Down
48 changes: 26 additions & 22 deletions libs/shared-secrets.def.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,15 @@
# prevent direct access
if (!defined("SYS11_SECRETS")) { die(""); }

# define GPG message parts
define("GPG_MESSAGE_COMMENT", "Comment:");
define("GPG_MESSAGE_COMMENT_DUMMY", "Dummy");
define("GPG_MESSAGE_LINE_LENGTH", 64);
define("GPG_MESSAGE_LINE_SEPARATOR", "\n");
define("GPG_MESSAGE_PARTS_MARKER", "=");
define("GPG_MESSAGE_VALUE_SEPARATOR", " ");
define("GPG_MESSAGE_PREFIX", "-----BEGIN PGP MESSAGE-----");
define("GPG_MESSAGE_SUFFIX", "-----END PGP MESSAGE-----");

# define stream buffer size
define("STREAM_BUFFER", 1024);
# define encoding markers
define("BASE64_MARKER_A", "+");
define("BASE64_MARKER_B", "/");
define("BASE64_MARKER_END", "=");
define("URL_BASE64_MARKER_A", "-");
define("URL_BASE64_MARKER_B", "_");
define("URL_ENCODE_MARKER", "%");

# define MySQL parameters
# define MySQL queries
define("MYSQL_READ", "SELECT COUNT(*) FROM secrets WHERE fingerprint = ?");
define("MYSQL_WRITE", "INSERT INTO secrets VALUES (?, ?, CURRENT_TIMESTAMP)");

Expand All @@ -26,15 +21,24 @@
define("READ_PAGE_NAME", "read");
define("SHARE_PAGE_NAME", "share");

# define parameter name
define("BASE64_MARKER_A", "+");
define("BASE64_MARKER_B", "/");
define("MAX_PARAM_SIZE", 512);
define("PARAM_NAME", "secret");
define("URL_BASE64_MARKER_A", "-");
define("URL_BASE64_MARKER_B", "_");
define("URL_ENCODE_MARKER", "%");
# define parameter values
define("MAX_PARAM_SIZE", 512);
define("PARAM_NAME", "secret");

# define stream buffer size
define("STREAM_BUFFER", 1024);

# define
# only define the legacy values if they are activated
if (SUPPORT_LEGACY_LINKS) {
# define GPG message parts
define("GPG_MESSAGE_COMMENT", "Comment:");
define("GPG_MESSAGE_COMMENT_DUMMY", "Dummy");
define("GPG_MESSAGE_LINE_LENGTH", 64);
define("GPG_MESSAGE_LINE_SEPARATOR", "\n");
define("GPG_MESSAGE_PARTS_MARKER", "=");
define("GPG_MESSAGE_VALUE_SEPARATOR", " ");
define("GPG_MESSAGE_PREFIX", "-----BEGIN PGP MESSAGE-----");
define("GPG_MESSAGE_SUFFIX", "-----END PGP MESSAGE-----");
}

?>
Loading

0 comments on commit d1a55ec

Please sign in to comment.