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

Commit

Permalink
creating secret sharing links and downloading the public key is now p…
Browse files Browse the repository at this point in the history
…ossible with only RSA public keys set as RSA_PRIVATE_KEYS
  • Loading branch information
yahesh committed Nov 15, 2019
1 parent 1a3fb90 commit 3bc63c9
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 44 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 0.24b0 (2019-11-15)

* introduced helper functions `is_privkey()` and `is_pubkey()`
* as a **share-only** doesn't need the private key, `RSA_PRIVATE_KEYS` can now also old RSA public keys
* creating secret sharing links and downloading the public key now also works when RSA public keys are set as `RSA_PRIVATE_KEYS`
* updated README to reflect the new feature

# 0.23b0 (2019-11-14)

* fixed read-only mode and introduced share-only mode
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,10 @@ Copy the `config/config.php.default` file to `config/config.php` and set the nec

### Read-Only and Share-Only Instances

The configuration allows you to set your instances into read-only and/or share-only mode. This can be useful if want to use a private **share-only** instance or custom software to create secret sharing sharing links but provide a public **read-only** instance to retrieve the generated secret sharing links.
The configuration allows you to set your instances into read-only and/or share-only mode. This can be useful if want to use a private **share-only** instance or custom software to create secret sharing sharing links but provide a public **read-only** instance to retrieve the generated secret sharing links. There are two more things to consider:

* A **share-only** instance does not need access to the RSA private key as it will not decrypt secret sharing links. Therefore, it is possible to configure the RSA public key of the corresponding **read-only** instance into the `RSA_PRIVATE_KEYS` array of a **share-only** instance.
* The basis for the creation of secret sharing link is the `SECRET_SHARING_URL` configuration value. In order for a **share-only** instance to generate correct secret sharing links you have to set the URL of the corresponding **read-only** instance as the `SECRET_SHARING_URL` configuration value of the **share-only** instance.

### TLS Recommendation

Expand Down
9 changes: 8 additions & 1 deletion actions/pub.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ function get_public_key(&$error) {
if (!READ_ONLY) {
# for shared-secrets we only support encryption with one key
$keys = array_keys(RSA_PRIVATE_KEYS);
$pubkey = open_pubkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]]);
$pubkey = null;
if (is_pubkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]])) {
# open the public key
$pubkey = openssl_pkey_get_public(RSA_PRIVATE_KEYS[$keys[count($keys)-1]]);
} elseif (is_privkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]])) {
# extract the public key from the private key
$pubkey = open_pubkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]]);
}
if (null !== $pubkey) {
try {
$result = get_keypem($pubkey);
Expand Down
73 changes: 41 additions & 32 deletions actions/read.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,71 @@ function read_secret($secret, &$error = null) {
$keys = array_keys(RSA_PRIVATE_KEYS);
$recipients = [];
foreach ($keys as $key) {
$privkey = open_privkey(RSA_PRIVATE_KEYS[$key]);
if (null !== $privkey) {
$recipients[] = $privkey;
if (is_privkey(RSA_PRIVATE_KEYS[$key])) {
# open the private key
$privkey = open_privkey(RSA_PRIVATE_KEYS[$key]);
if (null !== $privkey) {
$recipients[] = $privkey;
}
}
}

try {
$decrypted_secret = decrypt_v01($secret, $recipients, $decrypt_error, $fingerprint);
} finally {
$keys = array_keys($recipients);
foreach ($keys as $key) {
openssl_pkey_free($recipients[$key]);
}
if (0 < count($recipients)) {
try {
$decrypted_secret = decrypt_v01($secret, $recipients, $decrypt_error, $fingerprint);
} finally {
$keys = array_keys($recipients);
foreach ($keys as $key) {
openssl_pkey_free($recipients[$key]);
}

zeroize_array($recipients);
}
zeroize_array($recipients);
}

if (null !== $decrypted_secret) {
if ($link = mysqli_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_PORT)) {
try {
if ($statement = mysqli_prepare($link, MYSQL_WRITE)) {
$fingerprint = bin2hex($fingerprint);
if (null !== $decrypted_secret) {
if ($link = mysqli_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_PORT)) {
try {
if ($statement = mysqli_prepare($link, MYSQL_WRITE)) {
$fingerprint = bin2hex($fingerprint);

if (mysqli_stmt_bind_param($statement, "s", $fingerprint)) {
if (mysqli_stmt_execute($statement)) {
if (1 === mysqli_affected_rows($link)) {
$result = $decrypted_secret;
if (mysqli_stmt_bind_param($statement, "s", $fingerprint)) {
if (mysqli_stmt_execute($statement)) {
if (1 === mysqli_affected_rows($link)) {
$result = $decrypted_secret;
} else {
$error = "Secret has already been retrieved.";
}
} else {
$error = "Secret has already been retrieved.";
if (DEBUG_MODE) {
$error = "Insert statement could not be executed";
}
}
} else {
if (DEBUG_MODE) {
$error = "Insert statement could not be executed";
$error = "Insert statement parameters could not be bound.";
}
}
} else {
if (DEBUG_MODE) {
$error = "Insert statement parameters could not be bound.";
$error = "Insert statement could not be prepared.";
}
}
} else {
if (DEBUG_MODE) {
$error = "Insert statement could not be prepared.";
}
} finally {
mysqli_close($link);
}
} else {
if (DEBUG_MODE) {
$error = "Database connection could not be established.";
}
} finally {
mysqli_close($link);
}
} else {
if (DEBUG_MODE) {
$error = "Database connection could not be established.";
$error = "Decryption failed: $decrypt_error";
}
}
} else {
if (DEBUG_MODE) {
$error = "Decryption failed: $decrypt_error";
$error = "Private key could not be read.";
}
}
} else {
Expand Down
9 changes: 8 additions & 1 deletion actions/share.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ function share_secret($secret, &$error = null) {
if (MAX_PARAM_SIZE >= strlen($secret)) {
# for shared-secrets we only support encryption with one key
$keys = array_keys(RSA_PRIVATE_KEYS);
$pubkey = open_pubkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]]);
$pubkey = null;
if (is_pubkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]])) {
# open the public key
$pubkey = openssl_pkey_get_public(RSA_PRIVATE_KEYS[$keys[count($keys)-1]]);
} elseif (is_privkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]])) {
# extract the public key from the private key
$pubkey = open_pubkey(RSA_PRIVATE_KEYS[$keys[count($keys)-1]]);
}
if (null !== $pubkey) {
try {
$recipients = [$pubkey];
Expand Down
9 changes: 6 additions & 3 deletions config/config.php.default
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
# prevent direct access
if (!defined("SYS11_SECRETS")) { die(""); }

# this is an array containing the supported RSA privated keys for encryption and decryption, the LAST private key
# within the array is used to encrypt new secrets while all private keys are used to decrypt secrets, this allows
# for smooth key rollovers
# this is an array containing the supported RSA privated keys for encryption and decryption, the LAST RSA private key
# within the array is used to encrypt new secrets while all RSA private keys are used to decrypt secrets, this allows
# for smooth key rollovers; for share-only instances it is sufficient to set the RSA public key of the corresponding
# read-only instance here
define("RSA_PRIVATE_KEYS", ["-----BEGIN RSA PRIVATE KEY-----\n".
"...\n".
"...\n".
"...\n".
"-----END RSA PRIVATE KEY-----"]);

Expand Down
2 changes: 1 addition & 1 deletion index.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

# Shared-Secrets v0.23b0
# Shared-Secrets v0.24b0
#
# Copyright (c) 2016-2019, SysEleven GmbH
# All rights reserved.
Expand Down
6 changes: 4 additions & 2 deletions lib/shared-secrets.def.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
define("OPENSSL_MACMESSAGE", "macmessage");
define("OPENSSL_MESSAGE", "message");
define("OPENSSL_NONCE", "nonce");
define("OPENSSL_PEM_HEAD", "-----BEGIN PUBLIC KEY-----");
define("OPENSSL_PEM_TAIL", "-----END PUBLIC KEY-----");
define("OPENSSL_PEM_HEAD_PRIV", "-----BEGIN RSA PRIVATE KEY-----");
define("OPENSSL_PEM_TAIL_PRIV", "-----END RSA PRIVATE KEY-----");
define("OPENSSL_PEM_HEAD_PUB", "-----BEGIN PUBLIC KEY-----");
define("OPENSSL_PEM_TAIL_PUB", "-----END PUBLIC KEY-----");
define("OPENSSL_RSAKEYCOUNT", "rsakeycount");
define("OPENSSL_RSAKEYIDS", "rsakeyids");
define("OPENSSL_RSAKEYLENGTHS", "rsakeylengths");
Expand Down
34 changes: 31 additions & 3 deletions lib/shared-secrets.exec.php
Original file line number Diff line number Diff line change
Expand Up @@ -457,14 +457,42 @@ function encrypt_v01($message, $recipients, &$error = null) {
return $result;
}

function is_privkey($string) {
$result = false;

if (is_string($string)) {
// cleanup
$string = trim($string);

$result = ((0 === strcasecmp(OPENSSL_PEM_HEAD_PRIV, substr($string, 0, strlen(OPENSSL_PEM_HEAD_PRIV)))) &&
(0 === strcasecmp(OPENSSL_PEM_TAIL_PRIV, substr($string, -strlen(OPENSSL_PEM_TAIL_PRIV)))));
}

return $result;
}

function is_pubkey($string) {
$result = false;

if (is_string($string)) {
// cleanup
$string = trim($string);

$result = ((0 === strcasecmp(OPENSSL_PEM_HEAD_PUB, substr($string, 0, strlen(OPENSSL_PEM_HEAD_PUB)))) &&
(0 === strcasecmp(OPENSSL_PEM_TAIL_PUB, substr($string, -strlen(OPENSSL_PEM_TAIL_PUB)))));
}

return $result;
}

function get_keyid($key) {
$result = null;

$keypem = get_keypem($key);
if (null !== $keypem) {
if ((OPENSSL_PEM_HEAD === substr($keypem, 0, strlen(OPENSSL_PEM_HEAD))) &&
(OPENSSL_PEM_TAIL === substr($keypem, -strlen(OPENSSL_PEM_TAIL)))) {
$keyid = str_replace(["\n", "\r"], "", substr($keypem, strlen(OPENSSL_PEM_HEAD), -strlen(OPENSSL_PEM_TAIL)));
if (is_pubkey($keypem)) {
$keyid = str_replace(["\n", "\r"], "",
substr($keypem, strlen(OPENSSL_PEM_HEAD_PUB), -strlen(OPENSSL_PEM_TAIL_PUB)));
$keyid = base64_decode($keyid, true);
if (false !== $keyid) {
$result = hash("sha256", $keyid, true);
Expand Down

0 comments on commit 3bc63c9

Please sign in to comment.