Powens Documentation
DocumentationChangelogConsoleWebsite
  • Documentation
  • Integration guides
    • Quick Start
      • API Overview
      • Add a first user and connection
    • ➖Bank
      • Introduction to Bank
      • Bank integration guide
    • ➖Check
    • ➖Wealth
    • ➖Pay
      • Getting started with Pay
      • Initiating a one-time payment with the Webview
      • Initiating a bulk payment with the Webview
      • Initiating a recurring payment with the Webview
      • Cancelling a payment
      • Validating your implementation with the test connector
      • Advanced
        • Listing connectors with Pay enabled programmatically
        • Implementing your own payment validation webview
        • Confirming payments manually
        • Changing the manual expiration time
        • Changing the maximum amounts for payments
    • ➖Trust
    • ➖Advisory (obsolete)
    • ➖Indicators
    • SCA & connection states
    • Webhooks
    • Advanced
      • Custom connection implementation
      • End-to-end encryption
      • Response signature
  • SDK
    • Connect SDK
    • Powens Connect iOS
  • Reference
    • API Reference
    • Console & Webview documentation
  • Ressources
    • Tools
      • Institutions & capabilities
      • Demo integration
      • Demo product
    • Glossary
  • Changelog
  • Legal notice
Powered by GitBook
On this page
  • Endpoints support
  • Encryption steps
  • Examples

Was this helpful?

  1. Integration guides
  2. Advanced

End-to-end encryption

PreviousCustom connection implementationNextResponse signature

Last updated 1 year ago

Was this helpful?

Banking credentials are very sensitive data. As an integrator of our services, you must ensure that confidentiality is guaranteed all the way from the user interface where they are entered, to our API endpoint where they are consumed. The whole transmission flow must be processed over a , but it may still involve intermediate components such as third-party API servers or caches that are not legally authorized to handle cleartext credentials.

Implementing end-to-end encryption is mandatory for both BI agents and partners when not using our Connect webview. Encryption is strongly advised for white-mark contracts.

Our API allows you to secure user credentials transmission using , by encrypting values before they are transmitted to your intermediate architecture. The resulting payload can only be decrypted by our API.

UserUser InterfaceIntermediate APIOur APIEncrypt credentialsDecrypt credentials🔓 Enter credentials🔒 Encrypted credentials🔒 Encrypted credentials

Endpoints support

End-to-end encryption apply to the following endpoints:

  • for initial values of a connector's fields (this endpoint is only accessible to agents and white-mark contracts);

  • for values of transient additionnal fields;

  • Transfer update for values of transient additionnal fields;

  • , when implementing a validation webview.

Encryption steps

End-to-end encryption consists in substituting every cleartext sensitive values in HTTP requests with an encrypted . The resulting HTTP request body is still a JSON object, with modified values.

Before: Cleartext credentials as string value in request body

After: Sensitive values are encrypted in request body

We strongly advise relying on existing cryptography libraries to achieve proper JWE encryption. The choice of a library will likely vary with your specific environment and configuration. We suggest the following projects:

  • , a JavaScript library with good browser compatibility, available as an ;

  • , a Java library usable in Android native apps;

  • , a framework written in Swift, usable in iOS native apps;

  • , a Python2/3 implementation.

Implementation details vary with each library. They usually include the following steps:

  1. GET /publickey
  2. Import the key according to the library documentation.

  3. If needed, convert text values of credentials to raw bytes (UTF-8 encoding).

  4. Encrypt the payload according to the library documentation, with RSA-OAEP-256 padding and A256GCM algorithm. We require the key ID (kid) to be included in the JWE header.

  5. Serialize the JWE to its compact format (URL-safe Base64 parts delimited by period), ready to be sent to our API.

Examples

Obtain the public end-to-end encryption key associated with your API domain by calling the following endpoint. The key is available as a .

Encryption keys are available in the , on your domain's settings page.

TypeScript integration using library

  import { Jose } from 'jose-jwe-jws';

  async encrypt(values: { [key: string]: any }): Promise<{ [key: string]: any }> {
    // Import your public key
    const jwkRsa = JSON.parse('<Your public key here>') as JWKRSA;
    const key = await Jose.Utils.importRsaPublicKey(jwkRsa, 'RSA-OAEP');
    // Prepare an encrypter
    const cryptographer = new Jose.WebCryptographer();
    const encrypter = new Jose.JoseJWE.Encrypter(cryptographer, key);
    encrypter.addHeader('kid', jwkRsa.kid);
    // Encrypt cleartext values independently
    const encrypted: { [key: string]: string } = {};
    for (const k of Object.keys(values)) {
      encrypted[k] = await encrypter.encrypt(values[k]);
    }
    return encrypted;
  }
Kotlin integration using library
 import com.nimbusds.jose.*
  import com.nimbusds.jose.crypto.RSAEncrypter
  import com.nimbusds.jose.jwk.RSAKey

  fun encrypt(values: Map<String, Any>) : Map<String, String> {
    // Import your public key
    val key = RSAKey.parse('<Your public key here>')
    // Prepare an encrypter
    val header = JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM)
      .keyID(key.keyID)
      .build()
    val encrypter = RSAEncrypter(key)
    // Encrypt cleartext values independently
    return values.mapValues {
      JWEObject(header, Payload(it.value.toString().toByteArray()))
        .also { it.encrypt(encrypter) }
        .serialize()
    }
  }
Swift integration using library

  import JOSESwift

  func encrypt(values: [String: String]) throws -> [String: String] {
    // Import your public key
    let keyJson = try JSONSerialization.jsonObject(
      with: "<Your public key here>".data(using: .utf8)!,
      options: .allowFragments
    ) as? [String: String]
    guard let keyData = try? JSONSerialization.data(withJSONObject: keyJson) else { throw EncryptionError }
    let jwk = try? RSAPublicKey(data: keyData)
    let key = try? jwk?.converted(to: SecKey.self)
    // Prepare an encrypter
    var header = JWEHeader(algorithm: .RSAOAEP256, encryptionAlgorithm: .A256CBCHS512)
    header.kid = keyJson!["kid"]
    guard let encrypter = Encrypter(
      keyEncryptionAlgorithm: .RSAOAEP256,
      encryptionKey: key,
      contentEncyptionAlgorithm: .A256CBCHS512
    ) else { throw EncryptionError }
    // Encrypt cleartext values independently
    var encrypted: [String: String] = [:]
    for key in values.keys {
        guard let data = values[key]?.data(using: .utf8) else { throw EncryptionError }
        let payload = Payload(data)
        guard let jwe = try? JWE(header: header, payload: payload, encrypter: encrypter) else { throw EncryptionError }
        encrypted[key] = jwe.compactSerializedString
    }
    return encrypted
  }
POST /user/me/connections
{
  "id_connector": 33,
  "username": "john",
  "password": "cleartext"
}
POST /user/me/connections
{
  "id_connector": 33,
  "username": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
  "password": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…"
}
JSON Web Key (JWK)
administration console
js-jose
Nimbus JOSE
JOSESwift
secure transport protocol
asymmetric key cryptography
JSON Web Encryption (JWE) payload
js-jose
npm package
Nimbus JOSE
JOSESwift
jwcrypto
Connection creation
Connection update
Payment update for static field values