create new tag
, view all tags

Idea: EncryptPlugin

I have a need to store passwords securely in TWiki pages, accessible only by a selected group. Passwords need to be strongly encrypted.

There are already two plugins for content encryption:

  • TopicCryptPlugin: Encrypt parts of a topic for privacy and add digital signatures to topics -- seems like a comprehensive and secure solution
  • HidePasswordPlugin: Designed to hide password embedded in TWiki pages -- totally insecure, passwords are stored in plain text and can be viewed with raw=on
  • HideInEditModePlugin: Hide one or two blocks of text in the edit page -- unclear if secure, obsolete
  • EncryptedPagesPlugin: Java applet that provides the ability to store data on a page in an encrypted form -- never finished, obsolete
Of those plugins, only the TopicCryptPlugin seems to fit the bill, but the syntax is rather complicated for my needs.

Here is the proposed spec of a new EncryptPlugin:

  • User adds %ENCRYPT{"my secret text"}%.
  • On save, it gets converted to: %ENCRYPT{_dont_change="8ohLxtZj"}%, e.g. a variable containing a hash value.
  • Text is stored in encrypted form as custom meta data in the topic, such as %META:ENCRYPTPLUGIN{name="8ohLxtZj" value="a4sf,4lxot-w#ger^bwe+lk,wvbf:ad"}%
  • In view mode, %ENCRYPT{_dont_change="8ohLxtZj"}% is rendered as follows:
    • my secret text if viewed by author.
    • ***** if viewed by non-authorized user.
  • In edit mode, %ENCRYPT{_dont_change="8ohLxtZj"}% is rendered as follows:
    • %ENCRYPT{"my secret text" _dont_change="8ohLxtZj"}% if viewed by author, e.g. author can change the text.
    • %ENCRYPT{_dont_change="8ohLxtZj"}% if viewed by non-authorized user, e.g. they just see the hash value.
  • By default, only the author can see and edit encrypted text. It is possible to add an allow parameter, such as allow="SupportGroup", to restrict access to a group. The _dont_change="8ohLxtZj" hash contains the allow parameter, e.g. gets invalidated if a non-member changes the allow parameter.

-- PeterThoeny - 2010-02-01

I refined above spec a bit.

-- PeterThoeny - 2010-09-01

I created EncryptPlugin with preliminary spec/doc. Anyone interested in implementing this? I have the code skeleton done sans core functionality (not yet posted).

-- PeterThoeny - 2010-11-15

Looking at TopicCryptPlugin, there is certainly a lot there which could be reused. We might want to add Blowfish for speed?

I suggest we provide for both allow and deny with those values being either Users or Groups, and possibly an optional display parameter to control what (if anything) is displayed for non-authorized users.

So the Usage would be:

%<nop>ENCRYPT{"text to be encrypted" allow="List of Users, Groups" deny="list of users, groups" display="TWiki text to display to non-authorized users" }%

The %<nop>META:ENCRYPTPLUGIN{name="..." value="..."}% would be visible in raw=debug mode. I am not sure this matters? Though it does allow access to the raw encrypted data for someone who is motivated.

For more security, the allow and deny parameters could also be encrypted when the topic is viewed in raw mode, or edited by users not authorized.

-- CraigMeyer - 2010-11-29

I thought of just using allow for simplicity. For security defining an exclusive group for access is more secure. Defining a group that is excluded is more error-prone in daily use.

The META:ENCRYPTPLUGIN meta data is not visible in a raw=on view, but is in a raw=debug view. It does not matter as long as the encryption is secure, such as with an RSA key with enough bits.

The allow does not need to be encrypted as long as the allow and raw text is encrypted in the meta data. That is, when decrypting based on membership you can check if the decrypted group matches the one in allow.

-- PeterThoeny - 2010-11-29

I agree with keeping it simple, just use allow.

By the way? Is there a standard function which does the inList(user, list_string) checking. Meaning, given the User and a comma delimited string of mixed WikiNames and GroupNames... determine if that User is in the list. This something which is probably used all over the code. I found a version in TagMePlugin

I have started implementation of EncryptPlugin. I am using TDD (Test Driven Development), so I have unit tests to check each sub-function. Is there a Unit Test environment for TWiki when just running from the command line?

-- CraigMeyer - 2010-12-02

On group membership test, are you looking for TWiki::Func::isGroupMember() in TWikiFuncDotPm?

Great that you are committed to unit testing! See TestCasesTutorial.

-- PeterThoeny - 2010-12-03


Trying to learn the proper process for check-in of a new Plugin?

1) Do I first go to Develop Bugs WebChanges and create a new Entry?

creating an Enhancement, State: Being worked on, EncryptPlugin, waiting for: Me

2) I have checked out the svn trunk (and TWikiRelease0.5x00)

3) create a new directory in twikiplugins for EncryptPlugin

4) put the required code, topics in directory

5) Then check everything in?

Thank you,


-- CraigMeyer - 2010-12-04

As for the support function TWiki::Func::isGroupMember(). I was looking for something one level up. Here is the code I used, with slight modification from TagMePlugin

Note: I changed the split to allow for spaces around the comma's in the comma delimited list.

_inList() looks for the given User in the comma-delimited list of Users and Groups.

sub _inList ($$) {
    my($user, $comma_str) = @_;

    foreach $name (split(/\s*,\s*/, $comma_str) ){
        $name =~ s/(Main\.|\%MAINWEB\%\.)//go; # strip leading web.
        if( $name eq $user ||
            (TWiki::Func::isGroup($name) && TWiki::Func::isGroupMember($name, $user)) ){
            return( 1 );

} #_inList

-- CraigMeyer - 2010-12-04

Do all plugin work that is not part of the core distribution in the SVN trunk (don't use branches). My preliminary version is already at SVN:EncryptPlugin (it already includes all build stuff). Do a checkout of the whole trunk, see SubversionReadme and base your dev TWiki on this checkout.

Do a symbolic link "install" of all plugins you need using pseudo-install. Before you do that for EncryptPlugin, temporarily move away your code and topics. After pseudo-install, copy your code and topic back. When ready, build and upload the plugin. See details at BuildContribCookbook and PluginsInSubversion.

-- PeterThoeny - 2010-12-04

Oh, I just realized that I never checked in the skeleton code and doc I did in September. I just did. You can to an svn up on your twiki/trunk checkout, then copy your own code over it.

-- PeterThoeny - 2010-12-05

Ok, I did not find your code, and so started without it. I will do the update first, thanks for warning me smile

Good News, it is working.

It was written to handle multiple %<nop>ENCRYPT{}% calls per topic

I need to convert my Test::More unit tests into the TWiki unit tests.

I also need to add a few more tests for complete coverage.

It is currently using Blowfish, though it could use RC4.

I need to improve the key generation, handling. It can read/create real RSA keys (public and private), though they aren't being used right now.

I don't usually like to check stuff in, that I am satisfied with, but if you want to see it, I will check it in.

-- CraigMeyer - 2010-12-05

In order to handle multiple encrypts, I need to add an index argument to the META data.

When it signs (not really required) and then MD6 hashes the concatenation of allow_list + clear_text + index, the hash will be unique, even if one just copies the code several times.


  1. %ENCRYPT{"%GREEN> Jimmy Neutron %END_COLOR%>" allow="SmallGroup" display="%RED%You won't see this unless you are me %ENDCOLOR%" }%
  2. %ENCRYPT{"%GREEN> Jimmy Neutron %END_COLOR%>" allow="SmallGroup" display="%RED%You won't see this unless you are me %ENDCOLOR%" }%
  3. %ENCRYPT{"%GREEN> Jimmy Neutron %END_COLOR%>" allow="SmallGroup" display="%RED%You won't see this unless you are me %ENDCOLOR%" }%

Produces the following Meta:

%<nop>META:ENCRYPTPLUGIN{name="DcoCU7Q8mB+M0P9LHCfULwxUTlMK7zwRcFQ3URdWg/w" allow="SmallGroup" display="%25RED%25 You won't see this unless you are me %25ENDCOLOR%25" index="0" value="U2FsdGVkX1+04smdGiB+FpHmgHobmC7StSzjXmzHIB6fSX93+b6sMzXCY3/TUHhgVqHEt1uXG6w=%0a"}%
%<nop>META:ENCRYPTPLUGIN{name="dBEVUsm8SVElzzXZzBkvuCTWuTk5opcVlKH/+IVu2Mc" allow="SmallGroup" display="%25RED%25 You won't see this unless you are me %25ENDCOLOR%25" index="1" value="U2FsdGVkX1+0j/37uDuzVlpOVduYccmqYsZEEfooFW8ciKvKwTu+X1g04/eIewNaGa1UxItvxlY=%0a"}%
%<nop>META:ENCRYPTPLUGIN{name="cJGOYU+3cUm4VDwL9tvtLTthJ1V+GQGlkrOyFNkqGbE" allow="SmallGroup" display="%25RED%25 You won't see this unless you are me %25ENDCOLOR%25" index="2" value="U2FsdGVkX19i63Pe+OeRvlyCmBhLnVONsBuOpUdAs5kGHE6xebgMfO2Qlm73Q14i6MvkG6qhphY=%0a"}%

-- CraigMeyer - 2010-12-05

Good progress! You do not need an index for the meta data, the name="..." is the hash key. See docs at TWikiMetaDotPm, and study how META:FIELD and META:FILEATTACHMENT are implemented. Also look at my skeleton code. For example, my $value = $meta->get( 'ENCRYPTPLUGIN', $attrs->{_dont_change} ) will return the value for the key stored in the _dont_change parameter of the ENCRYPT variable.

-- PeterThoeny - 2010-12-05

The index is not for access. It is used to disambiguate repeated instances of the exact same %<nop>ENCRYPT{...}% statements. So that each usage has a corresponding META element.

By the way I checked it in late last night. I still need to fix the RC4 code, and setup the proper config handling for the password itself.

-- CraigMeyer - 2010-12-05

This plugin brings up an interesting question. Let's say this plugin is in use, in several topics. How do we handle an Admin changing the password? This would break all pre-existing instances? Should we save all old passwords, which are still in effect?

Should we go back, and fix up the old instances when the password changes? Warn the Admin, and not allow the password to be changed?

-- CraigMeyer - 2010-12-05

Should the Admin always have access to the clear text?

-- CraigMeyer - 2010-12-05

I would not worry about users duplicating an ENCRYPT with _dont_change meta hash key, this can be an undefined state.

How about adding some salt when building the meta hash key? This would avoid having the same meta hash key with identical to-encrypt-text.

If you feel the Blowfish is good enough there is may be no need for RC4?

I do not understand, why is the admin password needed? Possibly do with a separate password just for this plugin?

People in the TWikiAdminGroup are considered root users, e.g. they can have access to all content.

No issue if the plugin does not show the clear text to the admin in case not in the group specified. The admin could edit the group and add himself/herself anyway. It might be better not to show the admin the clear text, so that it is an explicit step to gain access.

-- PeterThoeny - 2010-12-05

Actually the index is effectively repeatable salt.

In the afterEditHandler(), the code recomputes the hash, to make sure the _dont_change parameter wasn't modified. The hash is computed with the: clear_text + index + allow and then RSA signed, and md6 hashed.

My concern about Admin's changing password wasn't stated clearly. I am concerned, that people will use the plugin, encrypt useful information. Then the TWiki decides to change the internal password for EncryptPlugin, for some reason. (Ex: Some Corporations have a policy of 90 day password changing.)

Once the EncryptPlugin internal password is changed, all the previously encrypted content is lost. This is my concern. We should warn the TWiki Admin, that previous encrypted content will be lost.

-- CraigMeyer - 2010-12-06

Just curious, why do you need the index as a parameter in the meta data? If _dont_change is computed to be unique is there a need for it? OK if user reorders the ENCRYPT variables in the page?

Ah, yes, makes sense on password change. Warning admin is good for first implementation.

I recommend to create a Config.spec so that admins can easily configure the the plugin using configure, including explanation such as password change warning. See example SVN:GoogleAnalyticsPlugin/lib/TWiki/Plugins/GoogleAnalyticsPlugin/Config.spec

-- PeterThoeny - 2010-12-06

Edit | Attach | Watch | Print version | History: r18 < r17 < r16 < r15 < r14 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r18 - 2010-12-06 - PeterThoeny
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by Perl Hosted by OICcam.com Ideas, requests, problems regarding TWiki? Send feedback. Ask community in the support forum.
Copyright © 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.