Cifrado de Mensajes

A veces, los mensajes requieren seguridad más allá de la seguridad a nivel de transporte, como SSL. Para estos casos, los conectores pueden configurarse para cifrar o descifrar mensajes al enviar o recibir mensajes, respectivamente. Esto sitúa la seguridad a nivel de aplicación además de cualquier mecanismo de seguridad a nivel de transporte que pueda estar en su lugar.

Interfaz Cripto

Para añadir cifrado de mensajes, se debe proporcionar una implementación de la interfaz Crypto al construir el conector. Si no se proporciona ninguna implementación de Crypto, entonces esta etapa se omite y el transport message se recibe tal cual.

La interfaz es simple y consiste en dos métodos, encriptar y desencriptar.

public interface Crypto {
    /**
     * @param plaintext        message to send
     * @param cryptoProperties properties to define encryption
     * @return encrypted message
     */
    String encrypt(String plaintext, CryptoProperties cryptoProperties);

    /**
     * @param payload          encrypted message received
     * @param cryptoProperties properties to define encryption
     * @return decrypted message
     */
    String decrypt(String payload, CryptoProperties cryptoProperties);
}

Configuración de Crypto

La biblioteca de conectores proporciona dos implementaciones de la interfaz Crypto. Estos son:

NoopCrypto

Esta es una clase de paso de texto plano que registrará los datos a nivel de DEBUG. Generalmente se utiliza para pruebas.

NoopCrypto no requiere configuración.

Crypto Simétrico

Requiere una clave para la encriptación y desencriptación que luego es utilizada por los métodos de encriptación. Se asume que la contraseña clave es la misma que la contraseña del almacén de claves.

La clase SymmetricCrypto requiere cierta configuración para funcionar. Las siguientes propiedades deben ser proporcionadas al construir una instancia de SymmetricCrypto.

Clave Descripción

keystorePath

La ruta absoluta al almacén de claves

tipo De Almacén De Claves

Tipo de almacén de claves como PKCS12

contraseña Del Almacén De Claves

Contraseña utilizada para el almacén de claves

transformación

Transformación de cifrado a utilizar, p. ej. "AES/CBC/NoPadding" Consulte los Javadocs)

Utilizando el constructor SymmetricCrypto, podemos instanciar una instancia.

SymmetricCrypto symmetricCrypto = SymmetricCrypto.builder()
        .withKeystorePath(keystorePath)
        .withKeystoreType("PKCS12")
        .withKeystorePassword("keystore-password")
        .withTransformation("AES/CBC/PKCS5Padding")
        .build();

Uso

Ambos envían y receive connector s tiene un campo de criptografía, que permite al desarrollador proporcionar una implementación de Crypto, o no, si no es necesario.

Los CryptoHeaders son necesarios para garantizar que se pase una clave y que la encriptación se pueda activar o desactivar a nivel de mensaje.

Send Connector Ejemplo

Crypto crypto = getSymmetricCrypto(); (1)
SendConnector
        .<ExampleType, ExampleType>builder(connectorName)
        .withActorSystem(actorSystem)
        .withConnectorTransport(connectorTransport)
        .withSendTransportMessageConverter(messageConverter)
        .withCorrelationIdExtractor(correlationIdExtractor)
        .withCorrelationService(correlationService)
        .withCrypto(crypto) (2)
        .build();
1 Obtiene una implementación de Crypto (simbólica en este ejemplo)
2 Proporciona la implementación de Crypto.

Receive Connector Ejemplo

Crypto crypto = new NoopCrypto(); (1)
ReceiveConnector
        .<ExampleType>builder(connectorName)
        .withActorSystem(actorSystem)
        .withConnectorTransport(connectorTransport)
        .withReceiveTransportMessageConverter(messageConverter)
        .withReceiveHandler(receiver)
        .withMessageLogger(messageLogger)
        .withProcessingContextExtractor(processingContextExtractor)
        .withCrypto(crypto) (2)
        .build();
1 Instancia la implementación de Crypto (sin operación en este ejemplo)
2 Proporciona la implementación de Crypto.

Encabezados de Mensajes Cripto

Al utilizar Crypto con conectores, los mensajes deben enviarse con los siguientes encabezados. Si no se proporcionan, se utilizarán los valores predeterminados.

Clave Descripción Predeterminado

keyAlias

El alias clave que se está utilizando

empty string

esquemaDeCifrado

El esquema de cifrado en uso. Puede configurarse a NOPS para deshabilitar la encriptación

AES

El enum CryptoHeader está incluido en la API.

public enum CryptoHeaders {
    KEY_ID("keyAlias"),
    SCHEME("encryptionScheme");

    private final String headerName;

    CryptoHeaders(String headerName) {
        this.headerName = headerName;
    }
}

Juntando todo esto, podemos crear un método para instanciar los encabezados de mensaje requeridos.

private MessageHeaders messageHeaders() {
    return new MessageHeaders()
            .putHeader(CryptoHeaders.KEY_ID.getHeaderName(), "GWPAY01")
            .putHeader(CryptoHeaders.SCHEME.getHeaderName(), "AES")
            .putHeader("msgKey", "value1");
}

Luego colóquelos en el transport message, junto con la carga útil en el SendTransportMessageConverter interfaz funcional que puede ser declarada utilizando una lambda.

private SendTransportMessageConverter<ExampleType> sendTransportMessageConverter() {
    return payload -> new TransportMessage(
            messageHeaders(), (1)
            serialisePayload(payload)
    );
}

El SendTransportMessageConverter puede ser utilizado al construir un sending connector y todos los mensajes enviados a través de él tendrán los CryptoHeaders configurados. Este simple ejemplo demuestra cómo establecer los encabezados de forma estática; sin embargo, pueden establecerse de manera dinámica en función de la carga útil si esto es necesario con un esfuerzo adicional mínimo.