How the Database Field Encryption Mechanism Works in ContiNew Admin

ContiNew Admin automatically encrypts sensitive database fields before persistence and decrypts them on retrieval using a MyBatis interceptor, RSA key pairs, and the @FieldEncrypt annotation.

The database field encryption mechanism in the continew-org/continew-admin repository protects sensitive data such as passwords, emails, and phone numbers by ensuring they remain encrypted at rest. This system leverages the continew-starter-encrypt-field starter library to provide transparent encryption that requires minimal code changes in business logic.

Core Components of the Encryption System

The encryption architecture consists of three primary parts that work together to secure data transparently.

@FieldEncrypt Annotation

The @FieldEncrypt annotation marks entity fields or mapper method parameters for automatic encryption. When applied to entity fields in classes like UserDO.java, it instructs the MyBatis interceptor to transform the data before database operations. The annotation supports custom encryptors via the encryptor parameter, such as PasswordEncoderEncryptor.class for password hashing.

EncryptHelper Utility

The EncryptHelper class provides static methods (encrypt and decrypt) for manual encryption when building query conditions. This utility is essential for operations like duplicate-checking, where raw values must be encrypted before comparison against stored ciphertext. According to the source code, this helper resides in the starter dependency at top.continew.starter.encrypt.field.util.EncryptHelper.

RSA Key Configuration

RSA asymmetric encryption powers the cryptographic operations. The system uses a public key for encryption and a private key for decryption. These keys are externalized through Spring configuration properties and loaded at startup by RsaProperties.java, ensuring credentials never exist in the source code.

How Field Encryption Works in Practice

Encrypting Entity Fields

Entity classes annotate sensitive fields with @FieldEncrypt. In continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java, the user entity declares encrypted columns:

@FieldEncrypt(encryptor = PasswordEncoderEncryptor.class)
private String password;

@FieldEncrypt
private String email;

@FieldEncrypt
private String phone;

When MyBatis executes INSERT or UPDATE statements, the interceptor automatically encrypts these values using the configured RSA public key (or specified encryptor). During SELECT operations, the interceptor decrypts the ciphertext using the private key before returning the entity to the application layer.

Encrypting Query Parameters

When services must query using raw values—such as checking if an email already exists—manual encryption is required before the value reaches MyBatis. In UserServiceImpl.java, the service calls EncryptHelper.encrypt() to prepare query parameters:

// Check for duplicate emails during import
List<String> existEmails = listExistByField(
    importUserList,
    row -> EncryptHelper.encrypt(row)
);

Similarly, when building lambda queries, encrypted values ensure comparisons match the stored ciphertext:

.lambdaQuery()
    .eq(UserDO::getEmail, EncryptHelper.encrypt(email))
    .eq(UserDO::getPhone, EncryptHelper.encrypt(phone));

Mapper-Level Parameter Encryption

Mapper interfaces can annotate method parameters directly, allowing MyBatis to encrypt arguments automatically before executing the query. In continew-system/src/main/java/top/continew/admin/system/mapper/user/UserMapper.java:

UserDO selectByPhone(@FieldEncrypt @Param("phone") String phone);
UserDO selectByEmail(@FieldEncrypt @Param("email") String email);

This approach eliminates the need for manual encryption in the service layer for these specific queries.

RSA Key Management and Configuration

The cryptographic keys are defined in environment-specific YAML configuration files (application-dev.yml and application-prod.yml) and loaded by continew-common/src/main/java/top/continew/admin/common/config/RsaProperties.java:

continew-starter:
  encrypt:
    field:
      public-key: ${ENCRYPT_PUBLIC_KEY}
      private-key: ${ENCRYPT_PRIVATE_KEY}

The RsaProperties class reads these values at application startup:

PUBLIC_KEY  = SpringUtil.getProperty("continew-starter.encrypt.field.public-key");
PRIVATE_KEY = SpringUtil.getProperty("continew-starter.encrypt.field.private-key");

By using environment variables (${ENCRYPT_PUBLIC_KEY} and ${ENCRYPT_PRIVATE_KEY}), the system ensures keys remain outside version control and can be rotated without code changes.

End-to-End Encryption Flow

The complete database field encryption mechanism follows this pipeline:

  1. Data Creation: The service receives plaintext sensitive data (password, email, phone).
  2. Persistence Encryption: MyBatis intercepts the INSERT/UPDATE, encrypts annotated fields with the RSA public key, and stores ciphertext.
  3. Storage: Encrypted values reside in the database, protecting against direct data exposure.
  4. Retrieval Decryption: MyBatis intercepts SELECT results, decrypts fields using the RSA private key, and returns plaintext entities to the application.
  5. Manual Query Encryption: For custom queries, services use EncryptHelper.encrypt() to match against encrypted columns.

Summary

  • Annotation-driven: The @FieldEncrypt annotation marks fields for transparent encryption without boilerplate code.
  • Dual-mode operation: Automatic encryption via MyBatis interceptor for entities, and manual encryption via EncryptHelper for query parameters.
  • RSA-based security: Asymmetric encryption ensures data encrypted with the public key can only be decrypted with the private key.
  • Environment configuration: Keys are externalized to YAML files using environment variables, supporting secure deployment practices.
  • Minimal intrusion: The system works with standard MyBatis operations, requiring no changes to SQL mappers for basic CRUD operations.

Frequently Asked Questions

What types of fields should be encrypted in ContiNew Admin?

Sensitive personally identifiable information (PII) such as email addresses, phone numbers, and passwords should be encrypted. In the ContiNew Admin codebase, the UserDO entity demonstrates this pattern by annotating these exact fields with @FieldEncrypt, ensuring that user credentials and contact information remain protected even if the database is compromised.

How does the encryption mechanism affect database queries?

The database field encryption mechanism requires special handling for query parameters. While SELECT operations automatically decrypt results, WHERE clauses comparing against encrypted columns must use the same encryption algorithm. Services call EncryptHelper.encrypt(value) to transform plaintext search terms into ciphertext before executing queries, ensuring the encrypted values match the stored data.

Where are the RSA encryption keys stored?

The RSA public and private keys are stored as environment variables referenced in the Spring Boot configuration files (application-dev.yml and application-prod.yml). The RsaProperties class loads these values at runtime using SpringUtil.getProperty(), keeping the actual keys out of source code and version control. This supports secure key rotation and prevents credential leakage through repository access.

Can I use a different encryption algorithm instead of RSA?

Yes, the @FieldEncrypt annotation accepts a custom encryptor parameter that specifies which encryption implementation to use. For example, passwords use PasswordEncoderEncryptor.class instead of the default RSA encryptor. You can implement the encryptor interface from the continew-starter-encrypt-field library to integrate alternative algorithms such as AES or custom hashing schemes while maintaining the same transparent interception behavior.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →