![Python package](https://github.com/jvanasco/insecure_but_secure_enough/workflows/Python%20package/badge.svg)
# Quick Overview
This package is "insecure", but secure enough.
The idea behing being "secure_enough" is to allow for "autologin cookies" and "instant login" urls for social web applications.
This package is very similar to "ItsDangerous" - which is now popular, but was unknown when this package was first written.
Two important things to note:
1. You should not use this module for financial transactions or sensitive info. That would be egregiously silly.
2. If you log someone in with this, you should note the login as "insecure" and subsequently require them to provide a password (or other authentication) to view sensitive data or any 'write' activity.
This package supports the following schemes for encrypting data:
1. RSA encryption
2. AES encryption
This package supports the following schemes for signing data:
1. No signing ( just serialize )
2. HMAC SHA1 signing
3. HMAC SHA256 signing
4. Request signing, as compatible with Facebook's auth scheme.
The data transformation order is as follows :
1. serialize ( convert to JSON )
2. base64 encode
3. ? obfuscate
4. ? encrypt
5. ? sign
# Background
Long ago, I had a class that would do a trivial encryption on cookie data,
coupled with a lightweight hash to handle timeout events. This way you wouldn't
always have to decrypt data to do a light verification.
The general flow was this:
To encode:
cookie = encypted_data + timestamp + hash(encrypted_data + timestamp + secret)
To decode:
(payload, timestamp, hash) = cookie
if hash != hash (payload, timestamp, secret):
raise InvalidHash()
if timestamp > timeout:
raise Timeout()
data = decrypt(payload)
The encryption I used was a lightweight port from a CPAN (Perl) module, so it
could be blown away in seconds today.
When i decided to re-implement this, looking around I found a handful of similar
projects - which I've borrowed heavily from.
They include:
* https://github.com/dziegler/django-urlcrypt/blob/master/urlcrypt/lib.py
* http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/api/session.html#pyramid.session.signed_serialize
* https://developers.facebook.com/docs/authentication/signed_request/
This largely re-implements all of those, along with some other functionality.
Right now, data is a `base64_url_encoded` version of a string, concatenated list,
or json object (for dicts). I opted against using `pickle`, because this format
makes it easier to work with other web technologies (js, php, etc).
This might move to an all json version one day.
Check `demo.py` to see an overview of how this works.
## Signed Requests
`signed_request_create` and `signed_request_verify`
are both handled as `@classmethods` - along with their support functions.
That means you can call them directly without an object instance.
I built them as `@classmethods` instead of package functions...
because if you want to extend the options for digest mods, you can just
subclass `SecureEnough` and overwrite `_digestmod` to add more providers.
## Encrypting and Signing Cookies
Encrypting cookies currently happens via a 'global' RSA key for an instance of
`SecureEnough()`. [you provide details for it in the `__init__()`]
You can use timestamped based app_secrets, obfuscators & rsa keys.
The flow is as such:
1. Subclass the `ConfigurationProvider()` and overwrite the relevant hooks.
The requesting mehtods pass a single argument - `timestamp` - which should
give you enough to go on.
Note that `app_secret` returns a string, while the obfuscator must return an
object that can `obfuscate` and `deobfuscate`; and `rsa_key` requires an
object that can `encrypt` and `decrypt`.
This libray provides default functionality through wrapper objects you can
mimic.
2. Instantiate a `SecureEnough()` object, and register the relevant providers
3. When encrypting data, `SecureEnough()` will ask the `ConfigurationProvider()`
for the approprite keys/secrets for the current `time()`. When decrypting
data, `SecureEnough()` will ask the `ConfigurationProvider()` for the
approprite keys/secrets for the time in the cookie/hash (if there is one).
This flow will allow you to easily create a plethora of site secrets and RSA
keys -- as in a new one each day -- which means that while this module is not
actually secure, it is Secure Enough for most web applications.
UNTESTED
* You can create "configuration objects" that accept a timestamp and return an
appropriate secret/encryption key
===================
The following files give an interactive demo:
https://github.com/jvanasco/insecure_but_secure_enough/blob/main/demo.py
https://github.com/jvanasco/insecure_but_secure_enough/blob/main/demo_performance.py
Also note that the github source distribution contains tests.
===================
# ToDo:
The timebased providers are largely untested.
* build out the demo and the test suite to support it.
--------------------------------------------------------------------------------
`insecure_but_secure_enough` is released under the MIT license
Raw data
{
"_id": null,
"home_page": "https://github.com/jvanasco/insecure_but_secure_enough",
"name": "insecure-but-secure-enough",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "web pylons pyramid",
"author": "Jonathan Vanasco",
"author_email": "jonathan@findmeon.com",
"download_url": "https://files.pythonhosted.org/packages/60/fe/0405be4ceee56a4b05942b6c877ed0c5b7a09f5c21346815942124ec56e6/insecure_but_secure_enough-0.2.0.tar.gz",
"platform": null,
"description": "![Python package](https://github.com/jvanasco/insecure_but_secure_enough/workflows/Python%20package/badge.svg)\n\n# Quick Overview\n\nThis package is \"insecure\", but secure enough.\n\nThe idea behing being \"secure_enough\" is to allow for \"autologin cookies\" and \"instant login\" urls for social web applications.\n\nThis package is very similar to \"ItsDangerous\" - which is now popular, but was unknown when this package was first written.\n\nTwo important things to note:\n\n1. You should not use this module for financial transactions or sensitive info. That would be egregiously silly.\n2. If you log someone in with this, you should note the login as \"insecure\" and subsequently require them to provide a password (or other authentication) to view sensitive data or any 'write' activity.\n\n\nThis package supports the following schemes for encrypting data:\n\n1. RSA encryption\n2. AES encryption\n\n\nThis package supports the following schemes for signing data:\n\n1. No signing ( just serialize )\n2. HMAC SHA1 signing\n3. HMAC SHA256 signing\n4. Request signing, as compatible with Facebook's auth scheme.\n\n\nThe data transformation order is as follows :\n\n1. serialize ( convert to JSON )\n2. base64 encode\n3. ? obfuscate\n4. ? encrypt\n5. ? sign\n\n\n# Background\n\nLong ago, I had a class that would do a trivial encryption on cookie data,\ncoupled with a lightweight hash to handle timeout events. This way you wouldn't\nalways have to decrypt data to do a light verification.\n\nThe general flow was this:\n\nTo encode:\n cookie = encypted_data + timestamp + hash(encrypted_data + timestamp + secret)\n\nTo decode:\n (payload, timestamp, hash) = cookie\n if hash != hash (payload, timestamp, secret):\n raise InvalidHash()\n if timestamp > timeout:\n raise Timeout()\n data = decrypt(payload)\n\nThe encryption I used was a lightweight port from a CPAN (Perl) module, so it\ncould be blown away in seconds today.\n\nWhen i decided to re-implement this, looking around I found a handful of similar\nprojects - which I've borrowed heavily from.\n\nThey include:\n\n* https://github.com/dziegler/django-urlcrypt/blob/master/urlcrypt/lib.py\n* http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/api/session.html#pyramid.session.signed_serialize\n* https://developers.facebook.com/docs/authentication/signed_request/\n\nThis largely re-implements all of those, along with some other functionality.\n\nRight now, data is a `base64_url_encoded` version of a string, concatenated list,\nor json object (for dicts). I opted against using `pickle`, because this format\nmakes it easier to work with other web technologies (js, php, etc).\nThis might move to an all json version one day.\n\nCheck `demo.py` to see an overview of how this works.\n\n## Signed Requests\n\n`signed_request_create` and `signed_request_verify`\n\nare both handled as `@classmethods` - along with their support functions.\nThat means you can call them directly without an object instance.\n\nI built them as `@classmethods` instead of package functions...\nbecause if you want to extend the options for digest mods, you can just\nsubclass `SecureEnough` and overwrite `_digestmod` to add more providers.\n\n## Encrypting and Signing Cookies\n\nEncrypting cookies currently happens via a 'global' RSA key for an instance of\n`SecureEnough()`. [you provide details for it in the `__init__()`]\n\nYou can use timestamped based app_secrets, obfuscators & rsa keys.\n\nThe flow is as such:\n\n1. Subclass the `ConfigurationProvider()` and overwrite the relevant hooks.\n The requesting mehtods pass a single argument - `timestamp` - which should\n give you enough to go on.\n Note that `app_secret` returns a string, while the obfuscator must return an\n object that can `obfuscate` and `deobfuscate`; and `rsa_key` requires an\n object that can `encrypt` and `decrypt`.\n This libray provides default functionality through wrapper objects you can\n mimic.\n\n2. Instantiate a `SecureEnough()` object, and register the relevant providers\n\n3. When encrypting data, `SecureEnough()` will ask the `ConfigurationProvider()`\n for the approprite keys/secrets for the current `time()`. When decrypting\n data, `SecureEnough()` will ask the `ConfigurationProvider()` for the\n approprite keys/secrets for the time in the cookie/hash (if there is one).\n\nThis flow will allow you to easily create a plethora of site secrets and RSA\nkeys -- as in a new one each day -- which means that while this module is not\nactually secure, it is Secure Enough for most web applications.\n\n\nUNTESTED\n\n* You can create \"configuration objects\" that accept a timestamp and return an\nappropriate secret/encryption key\n\n\n===================\n\nThe following files give an interactive demo:\n\n\thttps://github.com/jvanasco/insecure_but_secure_enough/blob/main/demo.py\n\thttps://github.com/jvanasco/insecure_but_secure_enough/blob/main/demo_performance.py\n\nAlso note that the github source distribution contains tests.\n\n===================\n\n\n# ToDo:\n\nThe timebased providers are largely untested.\n* build out the demo and the test suite to support it.\n\n--------------------------------------------------------------------------------\n\n`insecure_but_secure_enough` is released under the MIT license\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Lightweight tools for signing and encrypting cookies, urls and stuff. This package isn't really secure, but it is secure enough for most needs.",
"version": "0.2.0",
"project_urls": {
"Homepage": "https://github.com/jvanasco/insecure_but_secure_enough"
},
"split_keywords": [
"web",
"pylons",
"pyramid"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "60fe0405be4ceee56a4b05942b6c877ed0c5b7a09f5c21346815942124ec56e6",
"md5": "15b5bf4a1ce7a99c8e330d113e99c447",
"sha256": "b5f25dcbc0a1008e9b201a4b29ee822873944536ddcc850e80e7640c7da2b92b"
},
"downloads": -1,
"filename": "insecure_but_secure_enough-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "15b5bf4a1ce7a99c8e330d113e99c447",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 17467,
"upload_time": "2024-04-09T18:46:28",
"upload_time_iso_8601": "2024-04-09T18:46:28.334377Z",
"url": "https://files.pythonhosted.org/packages/60/fe/0405be4ceee56a4b05942b6c877ed0c5b7a09f5c21346815942124ec56e6/insecure_but_secure_enough-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-09 18:46:28",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jvanasco",
"github_project": "insecure_but_secure_enough",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "insecure-but-secure-enough"
}