While couchcms is as far as I can judge a pretty safe cms, it doesn't have any security measures in the manner of encryption for data-at-rest.
While developing a personal project I wrote a little script, which encrypts data that is sent in by databound forms on the front-end. Which wouldn't have been possible without the help of trendoman. So here my thanks to you.
The script uses a standard databound form in combination with a bit of extra php and phpseclib.
A working example can be found in the attachment. All code is commented.
You can use encrypted and plain data side by side with this, since it works like a standard databound form if you use the bound type and as the encrypted form if you use any other type than bound + the variable chain that encrypts it all.
It only works for front-end creation and editing though, if you edit any input in the admin-panel all data will be saved unencrypted.
encryptdataboundforms.php
encryptdataboundforms-list.php
While developing a personal project I wrote a little script, which encrypts data that is sent in by databound forms on the front-end. Which wouldn't have been possible without the help of trendoman. So here my thanks to you.
The script uses a standard databound form in combination with a bit of extra php and phpseclib.
A working example can be found in the attachment. All code is commented.
You can use encrypted and plain data side by side with this, since it works like a standard databound form if you use the bound type and as the encrypted form if you use any other type than bound + the variable chain that encrypts it all.
It only works for front-end creation and editing though, if you edit any input in the admin-panel all data will be saved unencrypted.
encryptdataboundforms.php
- Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
<?php include('Crypt/Twofish.php'); ?>
<!-- The phplibrary in use here is phpseclib 1.0.5. All documentation about it can be found on its website -->
<?php
global $key;
$key = "8bLuVY294GU1DXT4IC63GeZdMTc8mXqu"
?>
<!-- As you can see, the key is in the same file that is used for creating the data. While that is fine for example purposes, you should of course never do that in a production environment
the safe storage of ciphers is a whole topic for itself and there are better tutorials for it than this html comment, so I won't give you any big pointers except for, that the cipher should
be stored on the same server as the data -->
<cms:template clonable="1" hidden="1">
<cms:editable type="text" label="Example Entry" name="example" />
<cms:editable type="text" label="Example Sub" name="sub_example" />
</cms:template>
<!DOCTYPE html>
<html>
<body>
<!-- Since the text should be shown in plaintext when accessing it you have to decrypt it. First the base64 string has to be decoded into the encrypted string and then that
has to be decrypted into plaintext. The extra step of encoding it in base64 is necessary so that couchcms can save the encrypted string to the db -->
<h3>String in the database:</h3>
<p>
<cms:show example />
</p>
<h3>String after it has been decoded from base64:</h3>
<p>
<cms:php>
echo base64_decode('<cms:show example />');
</cms:php>
</p>
<h3>Plaintext after decryption:</h3>
<p>
<cms:php>
$cipher = new Crypt_Twofish();
$cipher->setKey($key);
echo $cipher->decrypt(base64_decode('<cms:show example />'));
</cms:php>
</p>
<cms:set submit_success="<cms:get_flash 'submit_success' />" />
<cms:if submit_success >
<h4>The data has been saved</h4>
</cms:if>
<cms:form
masterpage=k_template_name
mode='edit'
page_id=k_page_id
enctype='multipart/form-data'
method='post'
anchor='0'
>
<cms:if k_success >
<!-- The entire encryption process happens here. The couchcms form variable is first encrypted with the help of phpseclib and then encoded in base64.
That string is then changed back from a normal php variable into a couchcms variable.
The second part below the encryption is the extra variable fpr sorting purposes which is just a substring of the original data without any encryption -->
<cms:php>
$cipher = new Crypt_Twofish();
$cipher->setKey($key);
$enc_example = base64_encode($cipher->encrypt('<cms:show frm_example />'));
global $CTX;
$CTX->set('db_example', $enc_example, 'global');
$sub_vorname = substr('<cms:show frm_example />', 0, 3);
$CTX->set('db_sub_example', $sub_example, 'global');
</cms:php>
<!-- In db-persist_form the encrypted couch variable is then finally saved into the database as the variable that was initially used in the form
Since the entire editing and creation process is on the front-end (if you would edit the data in the admin panel it would be saved unencrypted)
it didn't really matter what the title and name are. If you use those variables, that can of course be changed -->
<cms:db_persist_form
_invalidate_cache='0'
k_page_name = "<cms:random_name />"
k_page_title = "<cms:random_name />"
example = db_example
/>
<cms:if k_success >
<cms:set_flash name='success_msg' value='1' />
<cms:redirect k_page_link />
</cms:if>
</cms:if>
<cms:if k_error >
<div class="error">
<cms:each k_error >
<br><cms:show item />
</cms:each>
</div>
</cms:if>
<!-- The nice thing about this databound form is, that you can use encrypted data and unencrypted data with just a slight change.
If you want to encrypt the data, you have to use any other type than "bound" and of course write the entire variable chain to encrypt it.
If you want unencrypted data, for example a picture or some data that is not of a personal nature, you can just use the standard "bound" input. -->
<!-- The value of the input field has be decrypted beforehand for editing, otherwise the input is empty -->
<p><label>Example</label></p>
<p><cms:input name='example' type='text' value="<cms:php> $cipher = new Crypt_Twofish(); $cipher->setKey($key); echo $cipher->decrypt(base64_decode('<cms:show example />'));</cms:php>" /></p>
<cms:if "<cms:not submit_success />" >
<button type="submit">Speichern</button>
</cms:if>
</cms:form>
</body>
</html>
<?php COUCH::invoke(); ?>
encryptdataboundforms-list.php
- Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
<?php include('Crypt/Twofish.php'); ?>
<!-- The phplibrary in use here is phpseclib 1.0.5. All documentation about it can be found on its website -->
<?php
global $key;
$key = "8bLuVY294GU1DXT4IC63GeZdMTc8mXqu"
?>
<!-- As you can see, the key is in the same file that is used for creating the data. While that is fine for example purposes, you should of course never do that in a production environment
the safe storage of ciphers is a whole topic for itself and there are better tutorials for it than this html comment, so I won't give you any big pointers except for, that the cipher should
be stored on the same server as the data -->
<cms:template hidden="1" />
<!DOCTYPE html>
<html>
<body>
<!-- The list isn't sorted by the actual encrypted string, since after encoding it, it won't be the same as prior to encrypting it. As it should be. But that makes it useless for sorting
it in alphabetical order for example. Because of that a second variable is created that contains the first three characters of the unencrypted string. The number of characters can of course
be varied and if you don't need a list you can of course delete the entire second variable -->
<cms:pages masterpage='encryptdataboundforms.php' orderby='sub_example' order='asc'>
<a href="<cms:show k_page_link />">
<!-- Since the text should be shown in plaintext when accessing it you have to decrypt it. First the base64 string has to be decoded into the encrypted string and then that
has to be decrypted into plaintext. The extra step of encoding it in base64 is necessary so that couchcms can save the encrypted string to the db -->
<cms:php>
$cipher = new Crypt_Twofish();
$cipher->setKey($key);
echo $cipher->decrypt(base64_decode('<cms:show example />'));
</cms:php>
</a>
</cms:pages>
<cms:set submit_success="<cms:get_flash 'submit_success' />" />
<cms:if submit_success >
<h4>The data has been saved</h4>
</cms:if>
<cms:form
masterpage="encryptdataboundforms.php"
mode='create'
enctype='multipart/form-data'
method='post'
anchor='0'
>
<cms:if k_success >
<!-- The entire encryption process happens here. The couchcms form variable is first encrypted with the help of phpseclib and then encoded in base64.
That string is then changed back from a normal php variable into a couchcms variable.
The second part below the encryption is the extra variable fpr sorting purposes which is just a substring of the original data without any encryption -->
<cms:php>
$cipher = new Crypt_Twofish();
$cipher->setKey($key);
$enc_example = base64_encode($cipher->encrypt('<cms:show frm_example />'));
global $CTX;
$CTX->set('db_example', $enc_example, 'global');
$sub_vorname = substr('<cms:show frm_example />', 0, 3);
$CTX->set('db_sub_example', $sub_example, 'global');
</cms:php>
<!-- In db-persist_form the encrypted couch variable is then finally saved into the database as the variable that was initially used in the form
Since the entire editing and creation process is on the front-end (if you would edit the data in the admin panel it would be saved unencrypted)
it didn't really matter what the title and name are. If you use those variables, that can of course be changed -->
<cms:db_persist_form
_invalidate_cache='0'
k_page_name = "<cms:random_name />"
k_page_title = "<cms:random_name />"
example = db_example
/>
<cms:if k_success >
<cms:set_flash name='success_msg' value='1' />
<cms:redirect k_page_link />
</cms:if>
</cms:if>
<cms:if k_error >
<div class="error">
<cms:each k_error >
<br><cms:show item />
</cms:each>
</div>
</cms:if>
<!-- The nice thing about this databound form is, that you can use encrypted data and unencrypted data with just a slight change.
If you want to encrypt the data, you have to use any other type than "bound" and of course write the entire variable chain to encrypt it.
If you want unencrypted data, for example a picture or some data that is not of a personal nature, you can just use the standard "bound" input. -->
<p><label>Example</label></p>
<p><cms:input name='example' type='text' /></p>
<cms:if "<cms:not submit_success />" >
<button type="submit">Speichern</button>
</cms:if>
</cms:form>
</body>
</html>
<?php COUCH::invoke(); ?>