Skip to content
Permalink
Browse files

Initial import.

  • Loading branch information...
geertj committed Jul 25, 2012
1 parent 6c8e069 commit 8a4e837d513ec6f3cf29d20890a7a013566c693f
Showing with 22,263 additions and 1 deletion.
  1. +12 −0 .gitignore
  2. +1 −1 README
  3. +137 −0 doc/messagebus.txt
  4. +113 −0 doc/objects.txt
  5. +80 −0 doc/overview.txt
  6. +78 −0 doc/security.txt
  7. +167 −0 doc/syncapi.txt
  8. +15 −0 doc/thoughts.txt
  9. +11 −0 lib/bluepass/__init__.py
  10. +149 −0 lib/bluepass/backend.py
  11. +204 −0 lib/bluepass/crypto.py
  12. +7,789 −0 lib/bluepass/data/diceware.wordlist.asc
  13. +230 −0 lib/bluepass/database.py
  14. +90 −0 lib/bluepass/error.py
  15. +1 −0 lib/bluepass/ext/__init__.py
  16. +156 −0 lib/bluepass/ext/_sslex.c
  17. +913 −0 lib/bluepass/ext/openssl.c
  18. +178 −0 lib/bluepass/ext/secmem.c
  19. +99 −0 lib/bluepass/factory.py
  20. +15 −0 lib/bluepass/frontend.py
  21. +25 −0 lib/bluepass/keyring.py
  22. +143 −0 lib/bluepass/locator.py
  23. +31 −0 lib/bluepass/main.py
  24. +734 −0 lib/bluepass/messagebus.py
  25. +1,357 −0 lib/bluepass/model.py
  26. +141 −0 lib/bluepass/passwords.py
  27. +25 −0 lib/bluepass/platform/__init__.py
  28. +12 −0 lib/bluepass/platform/dummy/keyring.py
  29. +13 −0 lib/bluepass/platform/dummy/zeroconf.py
  30. +1 −0 lib/bluepass/platform/freedesktop/__init__.py
  31. +274 −0 lib/bluepass/platform/freedesktop/avahi.py
  32. +116 −0 lib/bluepass/platform/freedesktop/secrets.py
  33. +1 −0 lib/bluepass/platform/linux/__init__.py
  34. +36 −0 lib/bluepass/platform/linux/misc.py
  35. +1 −0 lib/bluepass/platform/posix/__init__.py
  36. +243 −0 lib/bluepass/platform/posix/backend.py
  37. +21 −0 lib/bluepass/platform/posix/errno.py
  38. +103 −0 lib/bluepass/platform/posix/misc.py
  39. +1 −0 lib/bluepass/platform/qt/__init__.py
  40. +41 −0 lib/bluepass/platform/qt/application.py
  41. +115 −0 lib/bluepass/platform/qt/backend.py
  42. +329 −0 lib/bluepass/platform/qt/dialogs.py
  43. +143 −0 lib/bluepass/platform/qt/frontend.py
  44. BIN lib/bluepass/platform/qt/icons/add.png
  45. BIN lib/bluepass/platform/qt/icons/bluepass.png
  46. BIN lib/bluepass/platform/qt/icons/clear.png
  47. BIN lib/bluepass/platform/qt/icons/eye.png
  48. BIN lib/bluepass/platform/qt/icons/menu.png
  49. BIN lib/bluepass/platform/qt/icons/search.png
  50. BIN lib/bluepass/platform/qt/icons/triangle-closed.png
  51. BIN lib/bluepass/platform/qt/icons/triangle-open.png
  52. +337 −0 lib/bluepass/platform/qt/mainwindow.py
  53. +125 −0 lib/bluepass/platform/qt/messagebus.py
  54. +315 −0 lib/bluepass/platform/qt/passwordbutton.py
  55. +966 −0 lib/bluepass/platform/qt/passwordview.py
  56. +104 −0 lib/bluepass/platform/qt/util.py
  57. +893 −0 lib/bluepass/platform/qt/vaultmanager.py
  58. +1 −0 lib/bluepass/platform/test/__init__.py
  59. +34 −0 lib/bluepass/platform/test/test_lock.py
  60. +39 −0 lib/bluepass/platform/windows/socket.py
  61. +29 −0 lib/bluepass/server.pem
  62. +234 −0 lib/bluepass/socketapi.py
  63. +795 −0 lib/bluepass/syncapi.py
  64. +190 −0 lib/bluepass/syncer.py
  65. +1 −0 lib/bluepass/test/__init__.py
  66. +4 −0 lib/bluepass/test/keys.py
  67. +20 −0 lib/bluepass/test/logging.conf
  68. +98 −0 lib/bluepass/test/test_backend.py
  69. +194 −0 lib/bluepass/test/test_crypto.py
  70. +162 −0 lib/bluepass/test/test_database.py
  71. +36 −0 lib/bluepass/test/test_keyring.py
  72. +108 −0 lib/bluepass/test/test_locator.py
  73. +141 −0 lib/bluepass/test/test_messagebus.py
  74. +254 −0 lib/bluepass/test/test_model.py
  75. +46 −0 lib/bluepass/test/test_passwords.py
  76. +80 −0 lib/bluepass/test/test_syncapi.py
  77. +49 −0 lib/bluepass/test/unit.py
  78. +236 −0 lib/bluepass/test/vectors/aes-cbc-pkcs7.txt
  79. +51 −0 lib/bluepass/test/vectors/hkdf.txt
  80. +40 −0 lib/bluepass/test/vectors/pbkdf2.txt
  81. +362 −0 lib/bluepass/test/vectors/rsa-oaep.txt
  82. +362 −0 lib/bluepass/test/vectors/rsa-pss.txt
  83. +1 −0 lib/bluepass/util/__init__.py
  84. +31 −0 lib/bluepass/util/base64.py
  85. +190 −0 lib/bluepass/util/json.py
  86. +33 −0 lib/bluepass/util/logging.py
  87. +13 −0 lib/bluepass/util/misc.py
  88. +36 −0 lib/bluepass/util/optparse.py
  89. +46 −0 lib/bluepass/util/selfpipe.py
  90. +83 −0 lib/bluepass/util/ssl.py
  91. +75 −0 lib/bluepass/util/test/test_json.py
  92. +98 −0 lib/bluepass/util/test/test_ssl.py
  93. +11 −0 lib/bluepass/util/uuid.py
  94. +2 −0 setup.cfg
  95. +127 −0 setup.py
  96. +88 −0 share/add.svg
  97. +78 −0 share/bluepass.svg
  98. +87 −0 share/clear.svg
  99. +88 −0 share/eye.svg
  100. +99 −0 share/menu.svg
  101. +82 −0 share/search.svg
  102. +87 −0 share/triangle.svg
  103. +30 −0 tools/aesvect.py
  104. +52 −0 tools/oakley.py
  105. +109 −0 tools/pkcs1vect.py
  106. +67 −0 tools/strength.py
@@ -0,0 +1,12 @@
*.pyc
*.so
lib/bluepass/_version.py
build/
dist/
trash/
*.egg-info
.*.swp
.*.swo
test.conf
header
*~
2 README
@@ -1 +1 @@
Welcome to Bluepass!
Welcome to Bluepass!!
@@ -0,0 +1,137 @@
Message Bus
===========

The communication between the Bluepass frontend and backend takes place via a
message bus. The message bus runs over a socket and transfers JSON messages in
both directions. The protocol is loosely modeled after D-BUS model but it is
simpler.

Why not use D-BUS? Because we need to support platforms where D-BUS is not
available by default, and i don't want to be required to provide packages for
those platforms.

Message Exchanges
=================

1. Method calls

A method call is initiated by the following message::

{
'type': 'method_call',
'serial': serial_number
'sender': 'sender_name',
'destination': 'destination_name',
'member': 'method_name',
'args': {}
}

The sender/destination fields specify the connection names (see below) of the
sender and the destination. The method field specifies the method to call. The
serial field is an integer that needs to be unique for each message generated
by this sender. The 'args' field is an object containing keyword arguments to
the method call.

A peer will reply to a 'method_call' message with a single 'method_return'
message::

{
'type': 'method_return',
'serial': serial_number',
'reply_serial': reply_serial_number,
'sender': 'sender_name',
'destination': 'destination_name',
'args': {}
}

The significance of the fields is as for a "method_call" message. In addition
"reply_serial" field identifies the message this method_return is a reply to.

If there is an error, the 'error' message is returned instead of a
"method_return":

{
'type': 'error',
'serial': serial_number',
'reply_serial': reply_serial_number,
'sender': 'sender_name',
'destination': 'destination_name',
'args': {
'error_name': 'string_id',
'error_message': 'textual error message'
}
}

The format is as for a "method_return" message with the addition that the
"args" field is guaranteed to have at least the "error_name" and the
"error_message" fields.

2. Signals

A signal is an asynchronous message that is not a reply to a method call but
instead signals an asynchronous condition that has happened::

{
'type': 'signal',
'serial': serial_number',
'sender': 'sender_name',
'destination': 'destination_name',
'member': 'signal_name',
'args': {}
}

The "destination" field for a signal is optional. If it is not set, it means
that the signal was sent to multiple connections on the message bus.


Connection Names
================

Each end point for the message bus connection has a name. The local name is
simply called the "name", and the remote name is called the "peer_name". The
local name is the peer name of the peer, and vice versa.

The server (= listening) side of a connection chooses a name before accepting
connections. The name chosen by the Bluepass backend is 'backend'. The client
(= connecting) side get a unique name from the server side during
authentication.


Authentication
==============

A simple, mutual authentication scheme based on HMAC and a shared secret is
implemented. The protocol uses the "authenticate" message to establish the
authentication. No message types other than "authenticate" may travel over the
connection before a connection is authenticated.

The client starts the authentication handshake like this:

{
'type': 'authenticate',
'method': 'hmac-magic-cookie-sha1',
'nonce': 'random_string',
'magic_cookie': 'cookie'
}

The value of "magic_cookie" is the HMAC of the nonce under the shared secret
and using the SHA1 hash function.

The server will respond to the handshake with this message::

{
'type': 'authenticate',
'method': 'hmac-magic-cookie-sha1',
'nonce': 'random_string_2',
'magic_cookie': 'cookie',
'name': 'name of server',
'peer_name': 'name assigned to client'
}

The client then uses the 'nonce' and 'magic_cookie' to authenticate the server.
In case of an authentication error (at either side), the connection must be
closed.

The mechanism for sharing the secret is not specified. Currently the backend
and the frontend are always started up by the same master process, so that can
generate the secret and share it with both sides.
@@ -0,0 +1,113 @@


# Store the vault/node/version unencrypted. This is required because we need
# it for efficient replication, and one of the security assumptions we have is
# that we do not

# vaults collection: this is not replicated

{
'id': 'uuid',
'_type': 'Vault',
'name': 'name',
'node': 'uuid',
'keys': {
'sign': {
'keytype': 'rsa',
'public': 'base64(asn1)',
'private': 'base64(encrypt(asn1,key,iv))',
'encinfo': {
'algo': 'aes-cbc-pkcs5',
'iv': 'base64(random)'
'kdf': 'pbkdf2-hmac-sha1',
'salt': 'base64(random)'
'count': n,
'length': bytes,
}
'pwcheck': {
'algo': 'hmac-magic-cookie-sha1',
'random': 'base64(random)',
'cookie': 'base64(hmac(key,random))'
}
},
'encrypt': { /* as sign */ },
}
}


# items collection: this is replicated
{
'id': 'uuid',
'_type': 'Item',
'vault': 'uuid',
'origin': {
'node': 'uuid',
'seqnr': 2
}
'payload': {
'_type': 'XXX',
...
},
'signature': {
'algo': 'rsa-pss-sha1',
'blob': 'xxx'
}
}

# Payload types

{
'id': 'uuid',
'_type': 'Certificate',
'node': 'uuid',
'name': 'name',
'keys': {
'sign': { 'key': 'xxx', 'keytype': 'rsa' }
'encrypt': { 'key': 'xxx', 'keytype': 'rsa' }
},
'restrictions': { 'synconly': false }
}

{
'_type': 'EncryptedPayload'
'algo': 'aes-cbc-pkcs5',
'iv': 'xxxx',
'blob': 'yyyy'
'keyalgo': 'rsa-oaep',
'keys' : { 'uuid': 'rsa encrypted symkey', ... }
}


# Contents of 'EncryptedPayload'

{
'id': 'uuid',
'parent': 'uuid',
'_type': 'Version',
'created_at': int
'deleted': bool,
'version': {
'_type': 'Type',
'id': 'uuid'
...
}
}

# Inside a version:

{
'_type': 'Password'
'id': 'uuid',
'name': 'name',
'comment': 'comment',
'group': 'group',
'password': 'password',
'generator': '[abc]',
}

{
'_type': 'Group',
'id': 'uuid',
'name': 'name'
'comment': 'comment'
}
@@ -0,0 +1,80 @@
Bluepass Synchronization
========================

A robust, secure and user friendly synchronization framework is one of the most
important features of Bluepass. In fact, Bluepass can be seen as a password
management application on top of the Bluepass synchronziation protocol. Other
types of applications on top of the same synchronization protocol could be
created as well.

First some definitions:

* A Bluepass instance is a copy of the Bluepass software running on a computer
system.
* A Bluepass database is a single file where a Bluepass instance stores its
data. There may be multiple Bluepass instances running on the same computer
system at any given time, but each will have a different database.
* A database contains multiple vaults. The vault is the basic unit of
synchronization. Each vault is replicated between one or more instances.
Each vault is identified in a globally unique way by a random UUID.
* Within a vault there are one or more nodes, each node corresponding to an
instance this vault is replicated to. Nodes are never shared between vaults.
So in case one instance has multiple vaults, it will have multiple nodes as
well, one for each vault. Each node is identified uniquely within a vault by
a random UID.

Bluepass Database
=================

A Bluepass database contains meta-data and replicated items. The meta-data
includes the local vault name, cryptographic keys specific to the instance, and
various settings and user preferences. Meta-data is specific to the instance
and never replicated.

Replicated items are the heart of the synchronization protocol. Each item is
stored in the database. The set of replicated items is a strict append-only
set. Items are never deleted only added (at some point we may implement pruning
to get rid of older items that are not needed anymore by the application, but
that would be a local optimization specific to the application and would not
impact synchronization at all).

Each item has a few important attributes:

* A type that identifies what kind of item this is.
* A UUID that uniquely identifies the item in the vault.
* An "origin", conisisting of the UUID of the node that created the item, and
a monotonically increasing sequence number local to the node.
* A cryptographic signature by made by the originating node.

Two types of items exist currently:

* Certificates. These are using for establishing trust between different nodes
in a vault.
* Encrypted items. These contain the actual passwords or other secret data.
As their name implies, encrypted items are stored encrypted.

(* A future version may add pruning of older versions. But this would be a
local operation on a Bluepass instance and woudl not be replicated. *

Synchronization Protocol
========================

When a vault is initially created, it have just one node. The database for a
vault will contain, in addition to some meta-data, one self-signed certificate
for the creation node, and zero encrypted items.

Encrypted items can now be added to the vault by the user. Each item wil refer to
the creation node as the origin, and will have a sequence number starting at 0
counting up monotonically.

To synchronize this vault with another Bluepass instances, a synchronization
protocol is defined. This synchronization protocol ("syncapi") is a simple
RESTful protocol that transfers JSON messages over HTTP. There are two basic
operations:

* Pairing: establish trust with a new instance on the network for a specific
vault. This operation will create a new node, and will add two certificates
to the vault: one signed by the original node for the new node, and one the
other way around. Pairing needs to happen before vaults can be synchronized.
* Synchronization: the actual trasfer of replicated items between different
bluepass instances that share a vault that was previously paired.
Oops, something went wrong.

0 comments on commit 8a4e837

Please sign in to comment.
You can’t perform that action at this time.