[cryptography] Fwd: Request for Reviewers

Richard Moore rich at kde.org
Fri Nov 29 08:10:12 EST 2013


The first attempt to send this didn't seem to go through, so I'm
resending with the attachment inline.

Hi All,

I've been asked to put together a design for a single sign on system
for the KDE project (www.kde.org) to use to provide a single login
server for all the various websites the project uses. If anyone has
time to take a look and see if I've left any design flaws then I'd
appreciate the feedback. The design is outlined at
http://xmelegance.org/devel/identitiy_kde_org/DESIGN and there's a
strawman python implementation (using pycrypto) at
http://xmelegance.org/devel/identitiy_kde_org/identity_kde_sso-0.4.tar.gz
that shows how the clients and server would work. I'll attach the
design document to this email in case that makes it easier for people.
Any feedback is appreciated.

Regards

Rich.

Introduction
============

This is the design of an SSO system to be used by identity.kde.org. The idea
is that all KDE websites should be able to use the IKO server to authenticate
users - the client websites should never have access to the user's
password. It is intended that non-KDE websites should also be able to deploy
this system in future, for example to support authenticating KDE developers
against IKO for login to upstream or downstream bug trackers.

The client part of the SSO system will need to be implementable in a wide
range of languages such as PHP, Ruby etc. in order to allow it to be
integrated into the existing codebase of the various websites.

Terms used in this document:

Client - The website that wishes to authenticate a user.
Server - The IKO website that has the credential information.

Note that all random numbers refered to in this document must be taken from a
secure random source.

Setup
=====

The design assumes that IKO and each client have a shared secret. It is not
possible to authenticate arbitrary websites using this model, only those that
have been pre-arranged.

Creating a Request
==================

When a client wishes to authenticate a user it generates an authentication
request, this is a token that it will pass to the server. It does this by
either redirecting the user to a specific URL on the server, or by an HTTP
POST. The request has the following structure:


  [IV][AES [Payload [NONCE]][PADDING]][HMAC]


IV - The IV used for this request. It is created by reading data from a secure
random source. We use the AES block size as the length of the IV (16 bytes).

Payload - The data be transfered to the server. Currently this is just the
nonce.

NONCE - A 16 byte random number used to ensure that the reply received is for
the correct request (replay protection). The nonce must be retained by the
client in order to verify the later reply from the server.

PADDING - PKCS5 padding that pads the payload to the AES block size.

In fact in the current implementation no padding is used here since the nonce
is specified to be the length of a single AES block. The padding will however
be required should further meta-data be introduced to requests. Padding is
handled using the PKCS5 method.

AES - The payload and padding are encrypted using AES in CBC mode. The cipher
is setup using the IV and the shared secret.

HMAC - An HMAC calculated using SHA1. The HMAC covers the IV and the encrypted
payload with padding.

Once the request has been created, it is base64 encoded to make it easy to
pass over HTTP. It could be passed to the IKO using a URL parameter or via an
HTTP POST.

Verifying a Request
===================

When the server receives a request, it must verify that it is genuine. The
server knows from either the HTTP Referer header, or through a parameter in
the HTTP message which client is making the request. It uses this knowledge to
select the key (shared secret) for the particular client.

The server first base64 decodes the request and verifies the HMAC. It then
extracts the IV and the encrypted block. The encrypted block is decripted
using the key and IV. The nonce is then extracted (since the length of the
nonce is fixed this is easy). If more meta-data is added to requests then
obviously additional steps will need to be taken to extract that too.

The server then authenticates the user. This could be by asking for a username
and password, using a 2 factor scheme or anything else. Persistent logins can
be offered using HTTP cookies avoiding the need for users reauthenticate for
each KDE website.

The server now knows the identity of the user, the client they are logging
into and the nonce that represents the authentication request.

Creating the Reply
==================

The server now creates a reply that will be passed to the client. The reply
has the following structure:


  [IV][AES [Payload [NONCE][LENGTH][USERNAME]][PADDING]][HMAC]


IV - The IV used for this reply. It is created by reading data from a secure
random source. We use the AES block size as the length of the IV (16 bytes).
Note that this IV is NOT the same as the IV used in the request.

Payload - The data be transfered to the client. Currently, this is the nonce,
the length of the username and the username itself.

NONCE - The nonce that was provided in the request to which we are responding.

LENGTH - The length of the username in bytes. This is stored as a 4 byte
unsigned integer in network byte order.

USERNAME - The name of the user. This should be encoded as UTF8.

PADDING - PKCS5 padding that pads the payload to the AES block size.

AES - The payload and padding are encrypted using AES in CBC mode. The cipher
is setup using the IV and the shared secret.

HMAC - An HMAC calculated using SHA1. The HMAC covers the IV and the encrypted
payload with padding.

Once the reply has been created, it is base64 encoded to make it easy to
pass over HTTP. It could be passed to the client by redirecting the user to a
known URL or by returning the user back to the referer of the initial
authentication request.

Verifying the Reply
===================

The client now receives the reply and must verify that it is genuine. It first
base64 decodes the reply and verifies the HMAC. It then extracts the IV and
the encrypted block. The encrypted block is decrypted using the key and
IV. The nonce is then extracted (since the length of the nonce is fixed this
is easy). If the nonce does not correspond to the one the client sent to the
server then the reply MUST be rejected as invalid. The client then reads the 4
byte length field to find the size of the username, and extracts the username
from the payload.

At this point the user is now authenticated and their username is known.

Questions and Caveats
=====================

Question: Would it be better to include the server in the token?

It cannot be encrypted since we need to use it to determine which key to
use. It could be protected by the HMAC however we'd need to extract it from
the token before verifying the HMAC is valid since again, we need to use this
information to determine which key to use.

Caveat: The length of the request and reply is not hidden.

A passive attacker can see the length of the payloads which could allow thing
to infer information about any metadata included in the payload of the
request, and the length of the username in the reply.

Question: Would it be better to use a counter mode instead of CBC?

Counter modes are easier to screw up and have less support in the various
crypto libraries of different languages. On the other hand they avoid the need
for padding and thereby avoid padding oracle attacks. The use of the HMAC
around the encrypted block in this design provides protection against these
attacks.

Author/Contact
==============

Richard J. Moore <rich at kde.org>


More information about the cryptography mailing list