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

Commit

Permalink
improved Mozilla Observatory rating publication on github
Browse files Browse the repository at this point in the history
  • Loading branch information
yahesh committed Sep 2, 2016
1 parent 734c14c commit 78f61f2
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 54 deletions.
62 changes: 37 additions & 25 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
# 0.4b0 (2016-09-30)
# 0.5b0 (2016-09-02)

* version bump for improved Mozilla Observatory rating publication on github

# 0.4b1 (2016-09-01)

* improved code so that A+ rating in Mozilla Observatory can be achieved
* added HTTP header configuration to readme
* modified the changelog so that it is more consistent
* updated the readme to describe how an A+ rating can be achieved
* tested improved code within chroot environment

# 0.4b0 (2016-08-30)

* version bump for integrity-checking feature publication on github

Expand All @@ -8,18 +20,18 @@
* introduced subresource integrity for link and style elements
* added asmCrypto.js.map for better debugging support
* switched from server-defined PBKDF2 salt to JavaScript-generated salt
* test implementation of new features within chroot environment
* tested implementation of new features within chroot environment

# 0.3b0 (2016-08-25)

* version bump for password-protection feature publication on github

# 0.2b2 (2016-08-25)

* improve length and handling of server-defined PBKDF2 salt
* fix escaping of password-protected secrets
* harmonize variable names of encryption and decryption code
* test implementation of password-protection feature within chroot environment
* improved length and handling of server-defined PBKDF2 salt
* fixed escaping of password-protected secrets
* harmonized variable names of encryption and decryption code
* tested implementation of password-protection feature within chroot environment

# 0.2b1 (2016-08-24)

Expand All @@ -34,41 +46,41 @@
* introduce support for GPG passphrase via passphrase file
* simplified index file structure
* fixed message unstripping which produced undecryptable results for certain lengths
* test implementation of shared-secrets service within chroot environment
* tested implementation of shared-secrets service within chroot environment

# 0.1b4 (2016-08-16)

* optimize copy-to-clipboard JavaScript integration
* fix error message handling
* add changelog file
* optimized copy-to-clipboard JavaScript integration
* fixed error message handling
* added changelog file

# 0.1b3 (2016-08-15)

* prepare publication on github
* introduce config parameters for customization
* update "how" page to be customizable
* add license file
* add readme file
* prepared publication on github
* introduced config parameters for customization
* updated "how" page to be customizable
* added license file
* added readme file

# 0.1b2 (2016-08-15)

* introduce copy-to-clipboard feature
* disable auto-form-fill of browsers
* introduced copy-to-clipboard feature
* disabled auto-form-fill of browsers

# 0.1b1 (2016-08-15)

* introduce cleaned-up code structure
* introduce action handling code
* introduce page handling code
* introduce template handling code
* introduce separate config.php file
* introduced cleaned-up code structure
* introduced action handling code
* introduced page handling code
* introduced template handling code
* introduced separate config.php file

# 0.1a2 (2016-08-11)

* allow URL-encoded and URL-unencoded secret URIs (Apple Mail bug)
* publish to internal git versioning
* allowed URL-encoded and URL-unencoded secret URIs (Apple Mail bug)
* published to internal git versioning

# 0.1a1 (2016-08-11)

* initial PoC release
* testing with first customer
* tested with first customer
55 changes: 44 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,39 @@ if (!-f $request_filename) {
}
```

Shared-Secrets is designed to yield an A+ rating at the [Mozilla Observatory](https://observatory.mozilla.org) website check. Releases are checked against the Mozilla Observatory to make sure that a good rating can be achieved.

To achieve an A+ rating with your instance, you have to implement TLS and non-TLS calls have to be redirected to the TLS-protected website (Nginx example):
```
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
# Your configuration comes here:
# ...
}
```

Furthermore the following HTTP headers have to be set (Nginx example):
```
add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'self'";
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload";
add_header X-Content-Security-Policy "default-src 'self'; frame-ancestors 'self'";
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Webkit-CSP "default-src 'self'; frame-ancestors 'self'";
add_header X-XSS-Protection "1; mode=block";
```

### MariaDB Setup

Shared-Secrets uses a single-table database to store who did retrieve which secret at what point in time. No actual secret content is stored. (The logging of IP addresses can be disabled through the configuration parameter LOG_IP_ADDRESS.):
Expand Down Expand Up @@ -70,21 +103,21 @@ It is strongly recommended to use TLS to protect the connection between the serv

## Attributions

* 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
* clipboard.js (https://clipboardjs.com): for simplifying the copy-to-clipboard use-case a lot
* 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
* [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
* [clipboard.js](https://clipboardjs.com): for simplifying the copy-to-clipboard use-case a lot
* [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
* switch to a more personalized design (current design is taken from https://github.com/twbs/bootstrap/tree/master/docs/examples/starter-template)
* switch to the [GnuPG PECL](https://pecl.php.net/package/gnupg) once the PHP 7 support is stable
* 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

## License

This application is released under the BSD license. See the LICENSE file for further information.
This application is released under the BSD license. See the [LICENSE](LICENSE) file for further information.
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.4b0
# Shared-Secrets v0.5b0
#
# Copyright (c) 2016, SysEleven GmbH
# All rights reserved.
Expand Down
2 changes: 1 addition & 1 deletion pages/read/get.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
?>

<h1>Read a Secret:</h1>
<p><pre id="read-secret"><?php print(htmlentities(SECRET_URI)); ?></pre></p>
<p><pre id="secret"><?php print(htmlentities(SECRET_URI)); ?></pre></p>

<form role="form" action="/<?php print(htmlentities(urlencode(SECRET_URI))); ?>" method="post">
<button type="submit" class="btn btn-default pull-right" id="read-secret-btn" name="read-secret-btn">Read the Secret!</button>
Expand Down
14 changes: 8 additions & 6 deletions pages/read/post.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<strong>Warning!</strong> You don't have JavaScript enabled. You will not be able to read password-protected secrets.
</div>
</noscript>
<div class="alert alert-danger" id="decrypt-error" style="display: none;">
<div class="alert alert-danger" id="decrypt-error">
<strong>Error!</strong> Local decryption failed.
</div>

Expand All @@ -38,15 +38,17 @@

?>

<label class="checkbox-inline" for="decrypt-locally"><input type="checkbox" autocomplete="off" id="decrypt-locally" value="" onclick="decrypt_locally();" />Password-protected: </label>
<input type="password" autocomplete="off" class="form-control" id="password" maxlength="64" size="32" style="display: inline; visibility: hidden; width: 25%;" />
<input type="button" class="btn btn-default" id="decrypt" style="visibility: hidden;" value="Unprotect!" onclick="decrypt();" />
<label class="checkbox-inline" for="decrypt-locally"><input type="checkbox" autocomplete="off" id="decrypt-locally" value="" />Password-protected: </label>
<input type="password" autocomplete="off" class="form-control" id="password" maxlength="64" size="32" />
<input type="button" class="btn btn-default" id="decrypt" value="Unprotect!" />

<link href="/resources/css/read.css" integrity="sha256-miIkI5gYeETYUyNUudOMl2RkZ9Akko+1KXYfxih5dD0=" rel="stylesheet" type="text/css" />

<script src="/vendors/asmcrypto/asmcrypto.js" integrity="sha256-+3Ja+u+3rug2giERjvQSkhc1GZ1jG8ebXZ5TbQe2890=" type="text/javascript"></script>
<script src="/vendors/buffer/index.js" integrity="sha256-+fItxTnTLDK8HaHyqiP4cD+RxwDK66DqoTE91HqUfnM=" type="text/javascript"></script>
<script src="/vendors/clipboard/clipboard.min.js" integrity="sha256-YPxFEfHAzLj9n2T+2UXAKGNCRUINk0BexppujiVhRH0=" type="text/javascript"></script>
<script src="/resources/js/copy-to-clipboard.js" integrity="sha256-pdoft+huio0ejiVD+B0WLnFm9Wab+1Yj1nODdPNAZI4=" type="text/javascript"></script>
<script src="/resources/js/decrypt.js" integrity="sha256-rbZOtsEWrdRylOtuKJGpCMFTvrU4AE2jy2fbbDLteqM=" type="text/javascript"></script>
<script src="/resources/js/copy-to-clipboard.js" integrity="sha256-LRwH9pTwY5TAE7KIJSReEy1y29iPc/AbugOTd1LOjrc=" type="text/javascript"></script>
<script src="/resources/js/read.js" integrity="sha256-c/Xg8fJJ0mVIZ7f/V5m0BWsgX3AQ/mgl1VOvXNBP4Ps=" type="text/javascript"></script>

<?php

Expand Down
14 changes: 8 additions & 6 deletions pages/share/get.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<strong>Warning!</strong> You don't have JavaScript enabled. You will not be able to share password-protected secrets.
</div>
</noscript>
<div class="alert alert-danger" id="encrypt-error" style="display: none;">
<div class="alert alert-danger" id="encrypt-error">
<strong>Error!</strong> Local encryption failed.
</div>

Expand All @@ -31,7 +31,7 @@
<form role="form" action="/<?php print(htmlentities(urlencode(SECRET_URI))); ?>" method="post">
<label for="secret"><h1>Share a Secret:</h1></label>
<input type="text" autocomplete="off" class="form-control" id="secret" name="secret" maxlength="512" size="512" />
<button type="submit" class="btn btn-default pull-right" id="share-secret-btn" name="share-secret-btn" style="margin-top: 0.5em;">Share the Secret!</button>
<button type="submit" class="btn btn-default pull-right" id="share-secret-btn" name="share-secret-btn">Share the Secret!</button>
</form>

<?php
Expand All @@ -40,13 +40,15 @@

?>

<label class="checkbox-inline" for="encrypt-locally"><input type="checkbox" autocomplete="off" id="encrypt-locally" value="" onclick="encrypt_locally();" />Password-protected: </label>
<input type="password" autocomplete="off" class="form-control" id="password" maxlength="64" size="32" style="display: inline; margin-top: 0.5em; visibility: hidden; width: 25%;" />
<input type="button" class="btn btn-default" id="encrypt" style="visibility: hidden;" value="Protect!" onclick="encrypt();" />
<label class="checkbox-inline" for="encrypt-locally"><input type="checkbox" autocomplete="off" id="encrypt-locally" value="" />Password-protected: </label>
<input type="password" autocomplete="off" class="form-control" id="password" maxlength="64" size="32" />
<input type="button" class="btn btn-default" id="encrypt" value="Protect!" />

<link href="/resources/css/share.css" integrity="sha256-d3wZL0SNgWVcA6m0aWipQ9T/4I0p55dnYZCVKzsaYlo=" rel="stylesheet" type="text/css" />

<script src="/vendors/asmcrypto/asmcrypto.js" integrity="sha256-+3Ja+u+3rug2giERjvQSkhc1GZ1jG8ebXZ5TbQe2890=" type="text/javascript"></script>
<script src="/vendors/buffer/index.js" integrity="sha256-+fItxTnTLDK8HaHyqiP4cD+RxwDK66DqoTE91HqUfnM=" type="text/javascript"></script>
<script src="/resources/js/encrypt.js" integrity="sha256-NlYh0r+uul7mzgrlyr+3IR6L3k/qYDR44WH7j9D4CzQ=" type="text/javascript"></script>
<script src="/resources/js/share.js" integrity="sha256-HJaUUzmSuv9fd99m8Fr1c/Mxh0J88JLL/R6xisdXTZ4=" type="text/javascript"></script>

<?php

Expand Down
6 changes: 3 additions & 3 deletions pages/share/post.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
?>

<h1>Share a Secret:</h1>
<p><pre id="share-secret"><?php print(share_secret(SECRET_PARAM)); ?></pre>
<button type="btn" class="btn btn-default pull-right" data-clipboard-target="#share-secret" id="copy-to-clipboard">Copy to Clipboard!</button></p>
<p><pre id="secret"><?php print(share_secret(SECRET_PARAM)); ?></pre>
<button type="btn" class="btn btn-default pull-right" data-clipboard-target="#secret" id="copy-to-clipboard">Copy to Clipboard!</button></p>

<script src="/vendors/clipboard/clipboard.min.js" integrity="sha256-YPxFEfHAzLj9n2T+2UXAKGNCRUINk0BexppujiVhRH0=" type="text/javascript"></script>
<script src="/resources/js/copy-to-clipboard.js" integrity="sha256-pdoft+huio0ejiVD+B0WLnFm9Wab+1Yj1nODdPNAZI4=" type="text/javascript"></script>
<script src="/resources/js/copy-to-clipboard.js" integrity="sha256-LRwH9pTwY5TAE7KIJSReEy1y29iPc/AbugOTd1LOjrc=" type="text/javascript"></script>

<?php

Expand Down
13 changes: 13 additions & 0 deletions resources/css/read.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#decrypt-error {
display: none;
}

#password {
display: inline;
visibility: hidden;
width: 25%;
}

#decrypt {
visibility: hidden;
}
18 changes: 18 additions & 0 deletions resources/css/share.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#encrypt-error {
display: none;
}

#share-secret-btn {
margin-top: 0.5em;
}

#password {
display: inline;
margin-top: 0.5em;
visibility: hidden;
width: 25%;
}

#encrypt {
visibility: hidden;
}
1 change: 0 additions & 1 deletion resources/js/copy-to-clipboard.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// find copy-to-clipboard button
var copy_to_clipboard = document.getElementById("copy-to-clipboard");

if (null != copy_to_clipboard) {
// check if we're confronted with a Safari browser
if ((-1 != navigator.userAgent.indexOf("Safari")) &&
Expand Down
81 changes: 81 additions & 0 deletions resources/js/read.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// find decrypt button
var decrypt_button = document.getElementById("decrypt");
if (null != decrypt_button) {
// attach onClick event
decrypt_button.addEventListener("click", function(){decrypt();});
}

// find decrypt-locally checkbox
var decrypt_locally_checkbox = document.getElementById("decrypt-locally");
if (null != decrypt_locally_checkbox) {
// attach onClick event
decrypt_locally_checkbox.addEventListener("click", function(){decrypt_locally();});
}

// action happening on local decryption
function decrypt() {
var result = decrypt_secret(document.getElementById("secret").innerHTML,
document.getElementById("password").value);

if (null != result) {
document.getElementById("secret").innerHTML = html_entities(result);

document.getElementById("decrypt").disabled = true;
document.getElementById("decrypt-locally").disabled = true;

document.getElementById("password").readOnly = "readonly";

document.getElementById("decrypt-error").style.display = "none";
} else {
document.getElementById("decrypt-error").style.display = "block";
}
}

// show/hide local decryption
function decrypt_locally(checkbox) {
if (document.getElementById("decrypt-locally").checked) {
document.getElementById("decrypt").style.visibility = "visible";
document.getElementById("password").style.visibility = "visible";
} else {
document.getElementById("decrypt").style.visibility = "hidden";
document.getElementById("password").style.visibility = "hidden";
}
}

// prevent code injection through locally decrypted secret
function html_entities(content) {
return content.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

function decrypt_secret(concatSecret, password) {
// these variables configure the PBKDF2 call
var outputLength = 32;
var workFactor = 1024;

// split concatenation of Base64-encoded salt and Base64-encoded encrypted secret
var base64Salt = concatSecret.substring(0, 44);
var base64Secret = concatSecret.substring(44);

// retrieve plain salt from Base64-encoded salt
var salt = (new buffer.SlowBuffer(base64Salt, "base64")).toArrayBuffer();

// retrieve plain secret from Base64-encoded encrypted secret
var secret = (new buffer.SlowBuffer(base64Secret, "base64")).toArrayBuffer();

// derive decryption key
var pbkdf2Key = asmCrypto.PBKDF2_HMAC_SHA256.bytes(password, salt, workFactor, outputLength);

try {
// decrypt secret with derived decryption key
var aesResult = asmCrypto.AES_GCM.decrypt(secret, pbkdf2Key, new Uint8Array(12));
} catch(err) {
var aesResult = null;
}

if (null != aesResult) {
// return UTF-8-encoded decrypted secret
return (new buffer.SlowBuffer(aesResult)).toString("utf-8");
} else {
return aesResult;
}
}
Loading

0 comments on commit 78f61f2

Please sign in to comment.