All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.adorsys.xs2a.adapter.deutschebank.DeutscheBankPsuPasswordEncryptionService Maven / Gradle / Ivy

There is a newer version: 0.1.18-alpha-release-candidate
Show newest version
package de.adorsys.xs2a.adapter.deutschebank;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.util.Base64;
import de.adorsys.xs2a.adapter.api.PsuPasswordEncryptionService;
import de.adorsys.xs2a.adapter.api.exception.PsuPasswordEncodingException;
import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/*
 * Deutsche bank password encryption flow is based on JWE (RFC7516 - https://tools.ietf.org/html/rfc7516)
 */
// TODO adjust this logic on the additional information from Deutsche bank about the certificates API
public class DeutscheBankPsuPasswordEncryptionService implements PsuPasswordEncryptionService {
    private static final String URL_TO_CERTIFICATE = "https://xs2a.db.com/pb/aspsp-certificates/tpp-pb-password_cert.pem";
    private static final String DEFAULT_EXCEPTION_MESSAGE = "Exception during Deutsche bank adapter PSU password encryption";

    private static DeutscheBankPsuPasswordEncryptionService encryptionService;

    private JWEHeader jweHeader;
    private JWEEncrypter jweEncrypter;

    public static DeutscheBankPsuPasswordEncryptionService getInstance() {
        if (encryptionService == null) {
            encryptionService = new DeutscheBankPsuPasswordEncryptionService();
        }

        return encryptionService;
    }

    private DeutscheBankPsuPasswordEncryptionService() {
        init();
    }

    @Override
    public String encrypt(String password) {
        JWEObject jweObject = new JWEObject(jweHeader, new Payload(password));

        try {
            jweObject.encrypt(jweEncrypter);
        } catch (JOSEException e) {
            throw new PsuPasswordEncodingException(DEFAULT_EXCEPTION_MESSAGE, e);
        }

        return jweObject.serialize();
    }

    private void init() {
        CertificateFactory certificateFactory = new CertificateFactory();

        try {
            URI certificateUri = new URI(URL_TO_CERTIFICATE);

            // Warning for unchecked assignment can be ignored,
            // as under the hood CertificateFactory#engineGenerateCertificates returns ArrayList,
            // even though java.util.Collection is mentioned as a return type.
            // See org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory#engineGenerateCertificates implementation for further details.
            @SuppressWarnings("unchecked")
            Collection certificates = certificateFactory.engineGenerateCertificates(certificateUri.toURL().openStream());

            if (certificates.isEmpty()) {
                throw new PsuPasswordEncodingException("No certificates have been provided by bank for PSU password encryption");
            }

            List x509Certificates = toX509Certificates(certificates);

            List x509CertificateChainEncoded = x509Certificates.stream()
                                                           .map(this::toBase64)
                                                           .collect(Collectors.toList());

            jweHeader = new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM)
                            .x509CertURL(certificateUri)
                            .x509CertChain(x509CertificateChainEncoded)
                            .build();

            jweEncrypter = new RSAEncrypter(RSAKey.parse(getBankCertificate(x509Certificates)));
        } catch (IOException | CertificateException | URISyntaxException | JOSEException e) {
            throw new PsuPasswordEncodingException(DEFAULT_EXCEPTION_MESSAGE, e);
        }
    }

    private List toX509Certificates(Collection certificates) {
        return certificates.stream()
                   .map(certificate -> {
                       if (!(certificate instanceof X509Certificate)) {
                           throw new PsuPasswordEncodingException("Certificate provided by bank is not a X509 type");
                       }
                       return (X509Certificate) certificate;
                   })
                   .collect(Collectors.toList());
    }

    private Base64 toBase64(X509Certificate certificate) {
        try {
            return Base64.encode(certificate.getEncoded());
        } catch (CertificateEncodingException e) {
            throw new PsuPasswordEncodingException(DEFAULT_EXCEPTION_MESSAGE, e);
        }
    }

    private X509Certificate getBankCertificate(List certificates) {
        return certificates.get(0);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy