diff --git a/CHANGELOG.md b/CHANGELOG.md index 19c1d02..c1815f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index 9d58d5f..7ed0e7f 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/actions/pub.php b/actions/pub.php index cf35956..67d6934 100644 --- a/actions/pub.php +++ b/actions/pub.php @@ -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); diff --git a/actions/read.php b/actions/read.php index 2fe9179..1f8d0a7 100644 --- a/actions/read.php +++ b/actions/read.php @@ -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 { diff --git a/actions/share.php b/actions/share.php index 0accbd3..39e51bf 100644 --- a/actions/share.php +++ b/actions/share.php @@ -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]; diff --git a/config/config.php.default b/config/config.php.default index aede24f..281ab57 100644 --- a/config/config.php.default +++ b/config/config.php.default @@ -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-----"]); diff --git a/index.php b/index.php index 9c6bb95..fecb717 100644 --- a/index.php +++ b/index.php @@ -1,6 +1,6 @@