Deterministic encryption with AES SIV and where it's indispensable

When it comes to symmetric block ciphers, there are several modes of operation. These differ in how the ciphertext that exceed the block size of the cipher is formed. With AES, for example, the block size is 128 bits. Without going into too much detail, it's important to know that you can't simply concatenate the ciphertexts produced by a block cipher without leaking plaintext data.

Most modes of operation rely on a so-called initialization vector or IV, which is a fixed-size byte input that (as opposed to the encryption key) doesn't need to be secret but is required to decrypt a ciphertext. There are different ways to generate such an IV. The most common are simply random IVs. However, randomness means that encrypting the same cleartext twice will result in two different ciphertexts. For many applications this is a desirable property, as an attacker wouldn't be able to determine whether two ciphertexts correspond to the same cleartext. However, for certain scenarios we strictly want a given cleartext to always encrypt to the same ciphertext. In this case we speak of deterministic encryption.

One mode of operation that allows such deterministic encryption is the SIV mode, specified in RFC 5297. SIV stands for synthetic initialization vector and works by deterministically deriving an IV from the input during encryption. The IV is then prepended to the ciphertext. During decryption it can then be used to validate the cleartext and therefore notice whether the ciphertext has been tampered with. This property makes it a so-called authenticated encryption algorithm.

One field of application of this algorithm is deterministic filename encryption, as used in the Cryptomator cloud encryption utility. Since Cryptomator is an open source project which has its encryption code published as separate libraries, other software can easily integrate it. Connect2id employed the AES SIV implementation in the OpenID Connect SDK to generate deterministic encrypted (pairwise) user identifiers, for increasing privacy in single sign-on.

Example user ID encryption with AES SIV:

user ID: alice
encrypted: Osy9fFgs2PRJAk9JE0-4d3kIvxMFOLpoyX_yVZZmkG4r

The open source nature of the Cryptomator AES SIV library allows for security audits to be performed. One was undertaken by Tim McLean on behalf of Connect2id and its finds were published on the project page. All found issues have been successfully resolved in close collaboration with the Cryptomator team.

The Cryptomator AES SIV library for Java can be found on GitHub:

https://github.com/cryptomator/siv-mode

Connect2id server 7.18.1 maintenance release

This is a maintenance release of the Connect2id server which fixes three issues in the code and the configuration. Two of those issues were introduced in v7.18, so you are encouraged to ignore it and update to this release instead.

You can find more information about the fixed issues in the released notes below.

Download

To download a ZIP package of Connect2id server 7.18.1:

https://connect2id.com/assets/products/server/download/7.18.1/Connect2id-server.zip

SHA-256: a871d49f2d27ec4bd913c492948c284553f2b66eade5215cf4a2bd762c7ff91c

As WAR package only:

https://connect2id.com/assets/products/server/download/7.18.1/c2id.war

SHA-256: fa844422babde8bf3dd4880eb785bc25550eefef8a7a541feeca5530e7900d31

Questions?

Contact Connect2id support.


Release notes

7.18.1 (2019-11-30)

Resolved issues

  • Fixes a bug introduced in 7.18 on fixing issue oauth-oidc-sdk/277 which caused client GET and PUT registration responses to return HTTP status code 201 instead of 200 on success (issues oauth-oidc-sdk/282, server/501).

  • A relying party initiated logout request with a post-logout redirection URI must produce an error on a missing ID token hint instead of not honouring the requested redirection (issue server/500).

  • Restores the uppercase name of JGROUPSPING table in default-jgroups-jdbc_ping-mysql.xml and default-jgroups-jdbc_ping-postgres95.xml, changed to lowercase in v7.18. Also sets the name to uppercase for the new default-jgroups-jdbc_ping-sqlserver.xml introduced in v7.18 (issue server/502).

  • Updates the default JDBC URL for MySQL databases in /WEB-INF/infinispan-*-mysql.xml and default-jgroups-jdbc_ping-mysql.xml with the more correct mysql database identifier instead of mariadb. This is done to prevent potential issues if client protocol compatibility between MySQL and MariaDB breaks at some point in future. JDBC URLs for MariaDB should use the mariadb identifier. For more information see https://mariadb.com/kb/en/library/about-mariadb-connector-j/#connection-strings (issue server/499).

Dependency changes

  • Upgrades to com.nimbusds:oauth2-oidc-sdk:6.18.2

Connect2id server 7.18 has Microsoft SQL Server support, new stateless clustering mode

November's 7.18 release of the OpenID Connect / OAuth 2.0 server focuses on updating backend database support and clustering.

Microsoft SQL server is now among the supported relational databases, alongside MySQL, PostgreSQL and H2. You can use SQL server v2016, v2017 and the newest v2019. The configuration guide for SQL Server explains the JDBC, username and password settings.

Connect2id server 7.18 also introduces a new stateless clustering mode where the server's entire data -- long-lived objects (such as client registrations) as well as short-lived objects (sessions) -- is persisted to the main database (MySQL, PostreSQL or SQL Server). This mode is intended as a simpler to deploy and manage alternative to the existing stateless cluster mode which requires a separate Redis database to cache data and store short-lived objects.

If you need assistance selecting an optimal clustering mode for your identity provider and token service don't hesitate to contact our technical support.

You can find more information about the new release in the notes below.

Download

To download a ZIP package of Connect2id server 7.18:

https://connect2id.com/assets/products/server/download/7.18/Connect2id-server.zip

SHA-256: b97c51c89be16ef295aa853f76cf4cf8765aa629044a8188c57c1c45170c6b49

As WAR package only:

https://connect2id.com/assets/products/server/download/7.18/c2id.war

SHA-256: 10e19f691fa148eb94ebe9b06667d30196632be81753bfeb19aae35e7409ec69

Questions?

Contact Connect2id support.


Release notes

7.18 (2019-11-25)

General

  • Adds support for persisting Connect2id server data to a Microsoft SQL Server 2016+ database. Available in the standard and multi-tenant Connect2id server editions.

  • Adds new stateless cluster mode where the entire Connect2id server data is persisted to an SQL database (MySQL, PostreSQL or SQL Server). Intended as a lightweight, simpler to deploy and manage alternative to the existing stateless cluster mode where the short-lived data (cached client JWK sets, sessions, etc) is stored in a Redis database. Available in the standard and multi-tenant Connect2id server editions.

Configuration

  • /WEB-INF/infinispan-*-sqlserver.xml

    New Infinispan configurations for persisting Connect2id server data to a Microsoft SQL Server database. Supported database versions are 2016 and later. The database can be created with the traditional SQL Server UCS-2 (UTF-16) encoding or with the UTF-8 encoding, which is supported since version 2019.

    Java system properties to configure the database connection:

    • dataSource.url -- Sets the JDBC URL to specify the database host, port, name and other options. The default value is jdbc:sqlserver://localhost:1433;databaseName=c2id;applicationName=c2id;

    • dataSource.user -- Sets the username. The default value is c2id.

    • dataSource.password -- Sets the user password.

    Support for SQL Server is available in the standard and multi-tenant Connect2id server editions.

  • /WEB-INF/infinispan-stateless-{mysql|postgres95|sqlserver}.xml

    Adds new stateless cluster mode where long-lived as well as cached and short-lived Connect2id server data is persisted to an SQL database. Intended as a lightweight, simpler to deploy and manage alternative to the existing stateless cluster mode where the short-lived data is stored in a Redis database. Available in the standard and multi-tenant Connect2id server editions.

Resolved issues

  • The client registration endpoint must return HTTP status code 201 instead of 200 on a successful POST (issue oauth-oidc-sdk/277).

  • Logs any unchecked exceptions when parsing token requests at the /token endpoint (OP6208) (issue server/484).

  • Logs any unchecked exceptions at the /jwks.json endpoint (OP3000) (issue server/486).

  • Adds tenant ID legal character check (allow alphanumeric, dash, underscore) to tenants web API POST operation (issue server/496).

  • Documents HikariCP configuration properties in the Infinispan configuration files with an SQL database (issue server/495).

Dependency changes

  • Upgrades to com.nimbusds:oauth2-oidc-sdk:6.18.1

  • Updates to com.nimbusds:tenant-manager:4.3

  • Updates to com.nimbusds:tenant-registry:5.1

  • Updates to com.nimbusds:oauth2-authz-store:13.9

  • Updates to com.nimbusds:oidc-session-store:13.3

  • Upgrades to com.nimbusds:infinispan-cachestore-sql:4.0.6

  • Upgrades to org.jooq.pro:jooq:3.12.2

  • Adds new dependency com.microsoft.sqlserver:mssql-jdbc:7.4.1.jre11

Pushed authorisation requests (PAR) in the OAuth 2.0 SDK

The brand new Pushed Authorisation Requests (PAR) draft is now supported in v6.17 of the OAuth 2.0 / OpenID Connect SDK. PAR is a simple mean to up the security of authorisation requests, by making them integrity protected and confidential, and if the OAuth client has credentials - also authenticated.

The security of regular authZ requests

With regular OAuth 2.0 the client passes the request parameters encoded into the redirection URL that sends the user's browser (agent) for login and consent to the authorisation server.

GET /authz?response_type=code
 &client_id=123
 &state=ri4saex8
 &scope=upload_doc
 &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: c2id.com

Because the URL is submitted via the browser, the query parameters are exposed to the user and can potentially be tampered with. Applications therefore cannot rely on the authorisation request being authenticated, integrity protected or confidential. Do we have a solution for applications which require these security properties?

Securing authZ requests with JWT

The OAuth 2.0 extension for JWT-secured authorisation requests (JAR) allows the parameters to be authenticated and integrity protected by means of JWS. If JWE is applied to the digitally signed or HMAC-protected JWT, the request parameters become confidential. JAR has been a feature of OpenID Connect and is readily supported by the Connect2id server.

In order to secure authorisation requests with JAR the client needs to perform JOSE cryptography at the application layer. This is relatively easy with libraries such as Nimbus JOSE+JWT, but still, few developers take advantage of the extra security of JAR, unless the application is required to conform to a hardened OAuth 2.0 profile, such as FAPI.

PAR security works without application layer cryptography

The new PAR spec allows OAuth clients to submit their authorisation requests in a way that guarantees their integrity and confidentiality, without the need to deal with cryptography at the application layer. It also works for public clients without credentials.

PAR's solution is simple - a new endpoint at the authorisation server where clients can POST their authorisation request directly. If the client is confidential it will be required to authenticate as it does at the token endpoint.

Example HTTP POST of an authorisation request where the client authenticates with its client_secret:

POST /par HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

response_type=code
&client_id=123
&state=ri4saex8
&scope=upload_doc
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

For a successful POST the server will return a handle, in the form of a URI, typically a URN, which is valid for some limited time and may be single use.

HTTP/1.1 201 Created
Cache-Control: no-cache, no-store
Content-Type: application/json

{
  "request_uri": "urn:ietf:params:oauth:request_uri:tioteej8",
  "expires_in": 60
}

The OAuth client then makes the actual authorisation request, passing the URI handle in the request_uri parameter. No other query parameters are needed!

GET /authz?request_uri=urn%3Aietf%3Aparams%3Aoauth%3Arequest_uri%3Atioteej8 HTTP/1.1
Host: c2id.com

The rest of the flow continues as usual for the requested response type.

No URL limits on the authZ request

PAR also removes potential size limitations on the authorisation request, to accommodate browsers which doesn't support long URLs.

What is the maximum length of a URL in different browsers?

PAR meshes nicely with JAR

The PAR endpoint accepts JARs submitted via the request parameter. An application which requires non-repudiation of the authorisation request can submit a signed JWT containing the parameters. On success the server will return the URI handle for the request_uri on the next step.

POST /par HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

request=eyJhbGciOiJSUzI1NiIsImtpZCI6ImsyYmRjIn0.ewogICAgImlzcyI6IC
JzNkJoZFJrcXQzIiwKICAgICJhdWQiOiAiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5j
b20iLAogICAgInJlc3BvbnNlX3R5cGUiOiAiY29kZSBpZF90b2tlbiIsCiAgICAiY2
xpZW50X2lkIjogInM2QmhkUmtxdDMiLAogICAgInJlZGlyZWN0X3VyaSI6ICJodHRw
czovL2NsaWVudC5leGFtcGxlLm9yZy9jYiIsCiAgICAic2NvcGUiOiAib3BlbmlkIi
wKICAgICJzdGF0ZSI6ICJhZjBpZmpzbGRraiIsCiAgICAibm9uY2UiOiAibi0wUzZf
V3pBMk1qIiwKICAgICJtYXhfYWdlIjogODY0MDAKfQ.Nsxa_18VUElVaPjqW_ToI1y
rEJ67BgKb5xsuZRVqzGkfKrOIX7BCx0biSxYGmjK9KJPctH1OC0iQJwXu5YVY-vnW0
_PLJb1C2HG-ztVzcnKZC2gE4i0vgQcpkUOCpW3SEYXnyWnKzuKzqSb1wAZALo5f89B
_p6QA6j6JwBSRvdVsDPdulW8lKxGTbH82czCaQ50rLAg3EYLYaCb4ik4I1zGXE4fvi
m9FIMs8OCMmzwIB5S-ujFfzwFjoyuPEV4hJnoVUmXR_W9typPf846lGwA8h9G9oNTI
uX8Ft2jfpnZdFmLg3_wr3Wa5q3a-lfbgF3S9H_8nN3j1i7tLR_5Nz-g

Making a PAR request with the OAuth 2.0 SDK

The OAuth 2.0 / OpenID Connect SDK was updated with new classes to support PAR:

Example usage:

// The PAR endpoint, obtained from AS metadata
URI endpoint = URI.create("https://c2id.com/par");

// Construct an OAuth 2.0 authorisation request as usual
AuthorizationRequest authzRequest = new AuthorizationRequest.Builder(
    new ResponseType("code"), clientID)
    .redirectURI(URI.create("https://example.com/cb"))
    .scope(new Scope("upload_doc"))
    .state(new State())
    .build();

// The client authenticates the same way as it's supposed at the
// token endpoint
ClientID clientID = new ClientID("123");
Secret clientSecret = new Secret("chele3faiYieNg4taoy8ingai3eili3b");
ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSecret);

// Create the PAR request and POST it
HTTPRequest httpRequest = new PushedAuthorizationRequest(
    endpoint, clientAuth, authzRequest)
    .toHTTPRequest();
HTTPResponse httpResponse = httpRequest.send();

// Process the PAR response
PushedAuthorizationResponse response = PushedAuthorizationResponse.parse(httpResponse);

if (! response.indicatesSuccess()) {
    System.err.println("PAR request failed: " + response.getErrorObject().getHTTPStatusCode());
    System.err.println("Optional error code: " + response.getErrorObject().getCode());
    return;
}

PushedAuthorizationSuccessResponse successResponse = response.toSuccessResponse();
System.out.println("Request URI: " + successResponse.getRequestURI());
System.out.println("Request URI expires in: " + successResponse.getLifetime() + " seconds");

// Construct the authZ request for the browser, with request_uri as
// the sole parameter
URI redirectURI = new AuthorizationRequest.Builder(requestURI)
    .endpointURI(URI.create("https://c2id.com/authz"))
    .build()
    .toURI()

OAuth 2.0 SDK release notes

version 6.17 (2019-10-25)

  • Adds support for OAuth 2.0 Pushed Authorization Requests (draft-lodderstedt-oauth-par-00), see PushedAuthorizationRequest, PushedAuthorizationResponse, PushedAuthorizationSuccessResponse, PushedAuthorizationSuccessResponse and AuthorizationServerEndpointMetadata classes.
  • Deprecates RequestObjectPOST classes.
  • Updates ErrorObject to support URL-encoded parameters.
  • Adds new AuthenticationRequestDetector utility.

Updates token validation in Nimbus JOSE+JWT 8

Version 8 of the Nimbus JOSE+JWT library updates the token validation framework.

When creating a JOSEProcessor or JWTProcessor they can now be configured to accept only tokens with a given typ (type) header parameter. Use of this header parameter is recommended to prevent accidental or malicious passing of a JWS or JWE of another type which happens to rely on identical claims.

For this reason the new JWT Profile for OAuth 2.0 Access Tokens sets this header to "at+jwt".

For example:

{
  "alg" : "RS256",
  "typ" : "at+jwt",
  "kid" : "AhXoh4fe"
}

The DefaultJWTClaimsVerifier was also updated, to enable configuration of exact audience and other claim matching, lists of JWT claim names that must be present and claims which presence is prohibited.

Here are some sample validation rules for an access token:

  • Expected audience (aud): https://demo.c2id.com/userinfo
  • Exact match claims: iss = https://demo.c2id.com
  • Names of claims that must be present: sub, cid, expscp
  • Names of prohibited claims: nonce

Example token claims:

{
  "iss" : "https://demo.c2id.com",
  "aud" : "https://demo.c2id.com/userinfo"
  "sub" : "alice",
  "cid" : "000123",
  "exp" : 1460345736,
  "scp" : ["openid","email","profile"],
  "clm" : ["!5v8H"],
  "uip" : {"groups":["admin","audit"]}
}

Use of the new features is explained in the updated article for validating JWT-encoded access tokens.


Release notes

version 8.0 (2019-10-15)

  • Adds new JOSEObjectTypeVerifier interface for verifying the "typ" (type) header parameter of processed JOSE objects. A configurable DefaultJOSEObjectTypeVerifier is provided.
  • Updates the ConfigurableJOSEProcessor interface with methods for setting a JWS and a JWE JOSEObjectTypeVerifier (API breaking change).
  • Updates the DefaultJOSEProcessor and DefaultJWTProcessor classes to support JWS and JWE "typ" (type) header parameter verification via the new JOSEObjectTypeVerifier interface.
  • Makes JOSEObject.hashCode() and JOSEObject.equals() case insensitive.
  • Removes exception caching in DefaultJOSEProcessor and DefaultJWTProcessor (iss #229).
  • JWK.parseFromPEMEncodedObjects should throw a JOSEException on a missing PEM-encoded public key required to construct the JWK (iss #331).

version 8.1 (2019-10-15)

  • Extends DefaultJWTClaimsVerifier with configurable checks for "iat", "exp", "nbf", "iss" and "aud".

version 8.2 (2019-10-17)

  • Redesigns DefaultJWTClaimsVerifier to support complex audience checks, arbitrary exact claim matching, presence and prohibited checks.