Open Banking with Impact

Join us on our mission to change finance so that the banking sector becomes more transparent, diverse and sustainable

Get Started

Signatures

How to generate a digital signature

Our Open Banking APIs mandate the use of a digital signature on all endpoints of the Xs2a Module.

Digital signatures are implemented as described by the NextGetPSD2 XS2A Framework (version 1.3 including Errata) which in turn references the Signing HTTP Messages draft version 10.

It should be noted that the NextGenPSD2NextGenPSD2 - The NextGenPSD2 XS2A Framework is a European standard framework for building PSD2 compliant XS2A (Access to account) APIs. This specification covers payment initiation, account information and confirmation of funds services. Our APIs implement version 1.3 (including Errata) of this specification. XS2A Framework version 1.3 Errata document specifies significant changes to the signing algorithm, namely that the Date has been removed from the headers to be signed and normalisation of headers have been made explicit (lower case letters for signed headers).

The below example demonstrates usage of the Forge Javascript cryptography library to sign a HTTP request. This code may be used to validate your signing algorithm but it should never be used in a production environment. Please take care not to expose your eIDASeIDAS - A set of standards for electronic identification and trust services for electronic transactions in the European Single Market. QSEALCQSEALC - A qualified Electronic Seal Certificate is a qualified digital certificate under the trust services defined in the eIDAS Regulation. A QSEAL certificate makes it possible for the owner of the certificate to create electronic seals on any data. The digital signature technology guarantees the integrity and authenticity of the signed/sealed data. certificate's private key to a web browser or otherwise be made publicly available.

var pki = forge.pki;
var sha256 = forge.md.sha256;
var rsa = pki.rsa;

var keyId = ...your CA certificate keyId;
var headers = ...your HTTP request headers;
var privateKey = ...your signing certificate privateKey in PEM format;

// Add digest header.
jqXhr.setRequestHeader('Digest', calculateMessageDigest(settings.data, headers));
// Add signature header.
jqXhr.setRequestHeader('Signature', calculateSignature(keyId, headers, privateKey));

function calculateMessageDigest(data) {
  return "SHA-256=" + btoa(sha256.create().update(data || []).digest().data);
}

function calculateSignature(keyId, headers, privateKey) {
  var headerNames = ['digest', 'x-request-id'];
  var algorithm = 'rsa-sha256';
  var pk = pki.privateKeyFromPem(privateKey);
  var signature = btoa(pk.sign(sha256.create().update(getSigningString(headers, headerNames))));
  return 'keyId="' + keyId + '",'
      + 'algorithm="' + algorithm + '",'
      + 'headers="' + headerNames.join(' ') + '",'
      + 'signature="' + signature + '"';
}

function getSigningString(headers, headerNames) {
  // map headers in the http request to lowercase, before matching with allowed signature headernames (which are in lower-case)
  var key, keys = Object.keys(headers);
  var n = keys.length;
  var lowerCaseHeaders={};
  while (n--) {
    key = keys[n];
    lowerCaseHeaders[key.toLowerCase()] = headers[key];
  }

  var lines = [];
  $(headerNames).each(function (i, headerName) {
    if (lowerCaseHeaders[headerName]) {
      lines.push(headerName + ": " + lowerCaseHeaders[headerName]);
    }
  });
  return lines.join('\n');
}

Parameter keyId calculation

The Berlin Group v1.3 specifies the following for the keyId parameter:

It shall be formatted as follows:
keyId="SN=XXX,CA=YYYYYY
YYYYYYYYYY"
where “XXX" is the serial
number of the certificate in
hexadecimal coding given in
the TPP-Signature-CertificateHeader and
"YYYYYYYYYYYYYYYY" is
the full Distinguished Name of
the Certification Authority
having produced this
certificate

Our implementation requires that the full Distinguished Name of
the Certification Authority be formatted in RFC1779 format as demonstrated by this code example. This is not clearly specified by the NextGenPSD2NextGenPSD2 - The NextGenPSD2 XS2A Framework is a European standard framework for building PSD2 compliant XS2A (Access to account) APIs. This specification covers payment initiation, account information and confirmation of funds services. Our APIs implement version 1.3 (including Errata) of this specification. specification and there is no intention to change our implementation at this time.

The Distinguished Name of the Certification Authority in RFC1779 format should look something like this, note that properties must be seperated by comma followed by space. The ordering of the properties is specific to your certificate and may differ from what is displayed here.

CN=CA PSD2 Seal, O=Test Certification Authority, OID.2.5.4.97=VATNL-0123456789, C=NL

The following Java code shows how to obtain this value from your QSEAL certificate

X509Certificate x509Certificate = ...;
String dn = x509Certificate.getIssuerX500Principal().getName(X500Principal.RFC1779)

Updated about a year ago

Signatures


How to generate a digital signature

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.