Yan Khonski
Yan Khonski

Reputation: 13083

How to encrypt Spring Boot application data in mongodb

I have a Spring Boot application that stores payment information in the database. The application has end-points

These endpoints are not secure itself, and I do not want to secure them on the application level. All traffic from the user goes to HTTPS proxy, which will decrypt it and forward to the application.

However, I use mongo atlas free version for prototyping https://www.mongodb.com/cloud/atlas/faq

All the data I put into the database must be encrypted. Even the document structure (fields names and types) must be encrypted.

How to encrypt a field does not work for me, because I want to encrypt the whole document. I do not want to use unofficial libraries like bellow (thus no one guarantees if the library is secure)

<dependency>
   <groupId>com.bol</groupId>
   <artifactId>spring-data-mongodb-encrypt</artifactId>
   <version>1.3.0</version>
</dependency>

One idea that came to me is to configure the application to use a password (somehow configured or generated at given moment of time).

/**
* Provides a password to encrypt a document.
**/
// TODO  How to do it better? I still have to improve it.
@Component
public class PasswordProviderImpl implements PasswordProvider {
    
    private static final byte[] MASTER_PASSWORD = {1, 11, 37, 166, 11, 77};

    @Autowired
    private Environment environment;

    // I do not care about the implementation yet
    public char [] getPassword() {
        final byte[] envPassword = environment.getProperty("appplicationPassword").toString().toByteArray();
        return envPassword;
    }
}
/**
* Encrypts input byte array with provided password, afterwards, cleans input data and password - populates them with zeros - 0.
**/
@Component
public class Encryptor {
    private PasswordProvider passwordProvider;

    public byte [] encrypt(final byte unecrypted) {
        final byte [] password = passwordProvider.getPassword();
        final byte [] encrypted = xor(unecrypted, password);
        makeZeros(password);
        makeZeros(unecrypted);
        return encrypted;
    }
    
    private void makeZeros(final byte[] array) { /*Implementation*/}
    private byte[] xor(final byte [] arg1, final byte[] arg2) {/*Implementation*/}
}
/**
* Represents a unit of data in my application. Its values and fields and structure - everything should be encrypted.
**/
public class Order {
    private ObjectId id;
    private Instant createdDate;
    private Instant updatedDate;
    private Money amount;
    private String additionalDetails;

    // gettters, setters, constructor
}

Converter, found Set MongoDb converter programmatically

/**
* It is declared application configuration. It defines how to store {@link Order} in mongodb
**/
@Component
public OrderConverter implements onverter<Order, SecuredOrder> {
    
    private ObjectMapper objectMapper;
    private Encryptor encryptor;
    private Base64Converter base64Converter;

    @Override 
    public SecuredOrder convert(Order source) { 
        final String json = objectMapper.writeValueAsString(source);
        final unencrypted = json.toByteArray();
        final byte[] encrypted = encryptor.encrypt(unencrypted);
        final String payload = base64Converter.toBase64(encrypted);
        return SecuredOrder.of(order.getId(), payload);
    }
}
public class SecuredOrder {
    private ObjectId id; // same as in order id
    private String encryptedPayload; // The converter will make it
}

@Service
public OrderService {
    public void saveOrder(Order order) {
        orderRepository.save(order);
    }
}

If you have done a similar thing, please give me a direction. I would really like to do it properly.

Also, mongodb provides encryption mechanism, so maybe I should use it?

https://docs.mongodb.com/manual/core/security-encryption-at-rest/

https://docs.mongodb.com/manual/core/security-encryption-at-rest/#encrypted-storage-engine

Upvotes: 0

Views: 3286

Answers (1)

Eric Green
Eric Green

Reputation: 1283

If you're able to use the WiredTiger storage engine and you are using MongoDB 3.2 or above, you can utilize it's Encryption at Rest capability (as you mentioned at the bottom of your post!), but be advised this is available for the enterprise version only.

Upvotes: 2

Related Questions