Reputation Provider-Client protocol: Difference between revisions
(→Keys: move from ad-hoc crypto to proper BER and PKCS#1) |
|||
(7 intermediate revisions by the same user not shown) | |||
Line 82: | Line 82: | ||
=== Keys === |
=== Keys === |
||
For the time being the keys used are RSA keys (to be used with OpenSSL via [http://sandbox.rulemaker.net/ngps/m2/ M2Crypto]). A public key (<code><var>pubkey</var></code>) in this protocol is expressed as a base64 encoded string that is the |
For the time being the keys used are RSA keys (to be used with OpenSSL via [http://sandbox.rulemaker.net/ngps/m2/ M2Crypto]). A public key (<code><var>pubkey</var></code>) in this protocol is expressed as a base64 encoded string that is the DER encoded representation of the public key. A signature is a base64 encoded string representation of a PKCS#1 signature with SHA-1 as hash. |
||
=== List of Commands === |
=== List of Commands === |
||
Line 90: | Line 90: | ||
|- style="vertical-align: top;" |
|- style="vertical-align: top;" |
||
! style="text-align: right;" | Synopsis: |
! style="text-align: right;" | Synopsis: |
||
| colspan="2" | <code> |
| colspan="2" | <code>authenticate <var>response_value</var></code><br/>→ <code><var>welcome_message</var></code> |
||
|- style="vertical-align: top;" |
|- style="vertical-align: top;" |
||
! style="text-align: right;" | Arguments: |
! style="text-align: right;" | Arguments: |
||
Line 116: | Line 116: | ||
|- style="vertical-align: top;" |
|- style="vertical-align: top;" |
||
! style="text-align: right;" | Arguments: |
! style="text-align: right;" | Arguments: |
||
| colspan="2" | <code><var>pubkey</var></code>: The client's public key, BASE64 encoded. |
| colspan="2" | <code><var>pubkey</var></code>: The client's public key, BASE64 encoded DER encoded RSA key. |
||
|- style="vertical-align: top;" |
|- style="vertical-align: top;" |
||
! style="text-align: right;" | State: |
! style="text-align: right;" | State: |
||
Line 153: | Line 153: | ||
! style="text-align: right; width: 1em;" | neg.: |
! style="text-align: right; width: 1em;" | neg.: |
||
| none |
| none |
||
|} |
|||
==== createAuthorTag ==== |
|||
{| |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Synopsis: |
|||
| colspan="2" | <code>createAuthorTag <var>ObjectKey</var></code><br/>→ <code><var>AuthorTag</var></code> |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Arguments: |
|||
| colspan="2" | <code><var>ObjectKey</var></code>: The ObjectKey that an AuthorTag should be created for. |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | State: |
|||
| colspan="2" | authenticated only |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Description: |
|||
| colspan="2" | Creates an AuthorTag for the given ObjectKey. An AuthorTag is represented as an XML snippet of the following form: <code><AuthorTag ObjectKey="<var>ObjectKey</var>" UserPseudonym="<var>UserPseudonym</var>" signature="<var>signature</var>" /></code>, where <code><var>UserPseudonym</var></code> is an opaque identifier consisting of hexadecimal characters and <code><var>signature</var></code> is a BASE64 PKCS#1 SHA-1 RSA signature over <code><var>ObjectKey</var>?<var>UserPseudonym</var></code>. |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" rowspan="2" | Response: |
|||
! style="text-align: right; width: 1em;" | pos.: |
|||
| <code><var>AuthorTag</var></code>: The created AuthorTag. |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right; width: 1em;" | neg.: |
|||
| |
|||
{| |
|||
! 409 |
|||
| The ObjectKey is already assigned to an AuthorTag (for another user). |
|||
|} |
|||
|} |
|||
==== getReputation ==== |
|||
{| |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Synopsis: |
|||
| colspan="2" | <code>getReputation <var>AuthorTagOrTags</var></code><br/>→ <code><var>reputations</var></code> |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Arguments: |
|||
| colspan="2" | <code><var>AuthorTagOrTags</var></code>: The AuthorTag or concatenation of AuthorTags that the reputation should be retrieved for. |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | State: |
|||
| colspan="2" | authenticated only |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Description: |
|||
| colspan="2" | Retrieves the reputation from a list of AuthorTags as returned by createAuthorTag. |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" rowspan="2" | Response: |
|||
! style="text-align: right; width: 1em;" | pos.: |
|||
| <code><var>reputation</var></code>: The reputation as a floating point number string. If multiple AuthorTags were requested then the response will be multiple floating point numers separated by spaces. |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right; width: 1em;" | neg.: |
|||
| |
|||
{| |
|||
! 403 |
|||
| The AuthorTag was not created by this Reputation Provider. |
|||
|- |
|||
! 404 |
|||
| The AuthorTag is not assigned to a reputation value on this Reputation Provider. |
|||
|} |
|||
Warning: This command will return a negative response if any of the AuthorTag queries fails. If more than one AuthorTag was requested and the command fails then it's not possible to tell which of the queries succeeded and which failed (and with which error code). In the error case you might want to retry with one query per AuthorTag to sort this out. |
|||
|} |
|||
==== submitFeedback ==== |
|||
{| |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Synopsis: |
|||
| colspan="2" | <code>submitFeedback <var>AuthorTag</var> <var>feedback</var></code><br/>→ ∅ |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" rowspan="2"| Arguments: |
|||
| colspan="2" | <code><var>AuthorTag</var></code>: The AuthorTag that the reputation should be submitted for. |
|||
|- |
|||
| colspan="2" | <code><var>feedback</var></code>: The feedback. An integer that is either <code>+1</code> or <code>-1</code>. |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | State: |
|||
| colspan="2" | authenticated only |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" | Description: |
|||
| colspan="2" | Submits the feedback on the document that is identified by the AuthorTag. Note that the syntax must be exactly as given: <code>submitFeedback</code>, one space, an AuthorTag string representation (arbitrary contents, but no line break), one space, the feedback as an string representation of an integer (no space!). |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right;" rowspan="2" | Response: |
|||
! style="text-align: right; width: 1em;" | pos.: |
|||
| none |
|||
|- style="vertical-align: top;" |
|||
! style="text-align: right; width: 1em;" | neg.: |
|||
| |
|||
{| |
|||
! 403 |
|||
| The AuthorTag was not created by this Reputation Provider. |
|||
|- |
|||
! 404 |
|||
| The AuthorTag is not assigned to a reputation value on this Reputation Provider. |
|||
|} |
|||
|} |
|} |
Latest revision as of 04:25, 19 June 2006
The Reputation Provider acts as a server and listens on port 2323.
Encryption
The server<->client protocol, or the sessions, should provide protection against:
- all passive attacks
- most active attacks
Specifically it seems to only be possible to protect against active attacks (man in the middle) if a trust relationship has already been established, e.g. the client knows the server's public key. (In order to provide confidentiality the server does not need to know the client's public key. This key only becomes important for authenticating clients. The user creation process is possible even for an unauthenticated client.)
To minimize the possibility of protocol design or implementation errors it would be best to use an already existing protocol and implementation, e.g. SSL/TLS and OpenSSL. Problem: SSL uses X.509 certificates and not raw keys. Certificates pose some dangers of introducing accidental side channels, for example through serial numbers, but add next to no additional value. Also: SSL is quite a complex protocol and widely deployed implementation errors (ASN.1!) have not been unheard of.
A homemade protocol would look something like this:
- diffie-hellmann between client and server
- server signs own diffie-hellmann parameters with own secret key
- when the client has verified this signature it knows that it is in fact talking to the right server
- connection is then in a state in which the client may
- transmit a user creation request, or
- authenticate itself by sending a signed version of its own diffie-hellmann parameter
Discussion
own protocol | SSL/TLS | |
---|---|---|
pro |
|
|
contra |
|
|
One compromise approach might be: Use SSL and a 'real' certificate for the server (allows verification through PKI) but only a raw key for the client. Then when the connection is set up and authentication is necessary, have the client transmit its public key and sign something with that key. Preferably some secret from the SSL connection (session key or master key perhaps?), but it's probably not possible to get access to this. Alternatively let the server send a challenge and have the client sign that (be wary of replay attacks and the such).
Payload
The cleartext protocol is simple and text-based. All commands are sent by the client. All commands and responses are single lines that end with a single newline ("\n"). The terminating newline is implied and not mentioned explicitly for the rest of this document because it is not technically considered to be a part of the command/response. A command or response MUST NOT have any newline anywhere except for the terminating newline.
Failure to follow any of the regulations in this protocol MAY lead to immediate termination of the connection.
Commands
Commands are single words with no space, followed by optional command specific data that is separated from the command by a single space. The command specific data generally consists of several parameters (with no spaces) concatenated with spaces.
Error Responses
Error responses start with an unhappy smiley, a single space and a three-digit error code, followed by an optional human readable error message. They MUST thus match the following regular expression (PCRE syntax):
/^:-\( \d{3}.*$/
Error codes
Code | Message | Explanation |
---|---|---|
400 | Bad command | The command was malformed or invalid. Note that the server has the option to immediately terminate the connection when it encounters a protocol error and is not obliged to send this response and keep going. |
401 | Authorization required | The command was not executed because the client must authenticate first. See the section on Authentication. A server MAY terminate the connection instead of sending this response if it is extremely paranoid. This is the recommended behaviour. (Remember: Just because you're paranoid doesn't mean that they're not after you.) |
Positive Responses
Positive responses start with a happy smiley, a single space and command specific data. Thus they MUST match the following regular expression (PCRE syntax):
/^:-\) .*$/
Authentication
Connections can be in two states: authenticated and unauthenticated (actually 'authentication-in-progress' can be counted as a third state). On unauthenticated connections only a minor subset of commands is available. When an unauthenticated client tries to access a command that needs authentication the server either sends a 401 error code or terminates the connection.
In order to perform the authentication procedure:
- The client sends an
login
command with its public key as a parameter. - The server sends a positive response with the challenge.
- The client sends an
authenticate
command with the signed challenge - Either
- the server acknowledges the successful authentication with a positive response, if the signature checks out, or
- should the authentication not be successful for any reason, then the server silently terminates the connection with no error message.
Authentication may be tried exactly once per connection. No other command may be sent between the start of the procedure (the login
command) and the reception of the positive response to the authenticate
command. Any deviation from this protocol is forbidden and MUST lead to a termination of the connection.
User creation works just like authentication, but the create
command is sent instead of the login
command. The other limits still apply: no command may be sent in between create
and authenticate
, only one try per connection, deviation leads to termination. Upon completion of the user creation process the connection will be in an authenticated state.
Keys
For the time being the keys used are RSA keys (to be used with OpenSSL via M2Crypto). A public key (pubkey
) in this protocol is expressed as a base64 encoded string that is the DER encoded representation of the public key. A signature is a base64 encoded string representation of a PKCS#1 signature with SHA-1 as hash.
List of Commands
authenticate
Synopsis: | authenticate response_value → welcome_message
| |
---|---|---|
Arguments: | response_value : The response to the challenge.
| |
State: | authentication-in-progress only | |
Description: | Completes the authentication procedure. Must immediately succeed the response to a login or create command.
| |
Response: | pos.: | welcome_message : An optional server welcome message, may be empty.
|
neg.: | none |
create
Synopsis: | create pubkey → challenge challenge_value
| |
---|---|---|
Arguments: | pubkey : The client's public key, BASE64 encoded DER encoded RSA key.
| |
State: | unauthenticated only | |
Description: | Initiates the user creation procedure. The server responds with a challenge which the client must sign and send back in an authenticate command.
| |
Response: | pos.: | challenge_value : The challenge, a BASE64 encoded opaque string.
|
neg.: | none |
login
Synopsis: | login pubkey → challenge challenge_value
| |
---|---|---|
Arguments: | pubkey : The client's public key, BASE64 encoded.
| |
State: | unauthenticated only | |
Description: | Initiates the authentication procedure. The server responds with a challenge which the client must sign and send back in an authenticate command.
| |
Response: | pos.: | challenge_value : The challenge, a BASE64 encoded opaque string.
|
neg.: | none |
createAuthorTag
Synopsis: | createAuthorTag ObjectKey → AuthorTag
| ||
---|---|---|---|
Arguments: | ObjectKey : The ObjectKey that an AuthorTag should be created for.
| ||
State: | authenticated only | ||
Description: | Creates an AuthorTag for the given ObjectKey. An AuthorTag is represented as an XML snippet of the following form: <AuthorTag ObjectKey="ObjectKey" UserPseudonym="UserPseudonym" signature="signature" /> , where UserPseudonym is an opaque identifier consisting of hexadecimal characters and signature is a BASE64 PKCS#1 SHA-1 RSA signature over ObjectKey?UserPseudonym .
| ||
Response: | pos.: | AuthorTag : The created AuthorTag.
| |
neg.: |
|
getReputation
Synopsis: | getReputation AuthorTagOrTags → reputations
| ||||
---|---|---|---|---|---|
Arguments: | AuthorTagOrTags : The AuthorTag or concatenation of AuthorTags that the reputation should be retrieved for.
| ||||
State: | authenticated only | ||||
Description: | Retrieves the reputation from a list of AuthorTags as returned by createAuthorTag. | ||||
Response: | pos.: | reputation : The reputation as a floating point number string. If multiple AuthorTags were requested then the response will be multiple floating point numers separated by spaces.
| |||
neg.: |
Warning: This command will return a negative response if any of the AuthorTag queries fails. If more than one AuthorTag was requested and the command fails then it's not possible to tell which of the queries succeeded and which failed (and with which error code). In the error case you might want to retry with one query per AuthorTag to sort this out. |
submitFeedback
Synopsis: | submitFeedback AuthorTag feedback → ∅ | ||||
---|---|---|---|---|---|
Arguments: | AuthorTag : The AuthorTag that the reputation should be submitted for.
| ||||
feedback : The feedback. An integer that is either +1 or -1 .
| |||||
State: | authenticated only | ||||
Description: | Submits the feedback on the document that is identified by the AuthorTag. Note that the syntax must be exactly as given: submitFeedback , one space, an AuthorTag string representation (arbitrary contents, but no line break), one space, the feedback as an string representation of an integer (no space!).
| ||||
Response: | pos.: | none | |||
neg.: |
|