Hi @p.belloy,
Like explained in the last thread on this topics, you could find below some proposal patches. For the moment it works well with Postgres & MySQL but not yet tested on Oracle.
With this patch, encrypted string field uses @Lob to avoid any problem of column size whilst to be able to keep min/max attributes usage. It also introduce a ‘large’ attribute in widget to be able to set the UI with the correct type (large = multiline input, not large = single line input)
diff --git a/axelor-gradle/src/main/groovy/com/axelor/tools/x2j/pojo/Property.groovy b/axelor-gradle/src/main/groovy/com/axelor/tools/x2j/pojo/Property.groovy
index 85990bc..5d0efda 100644
--- a/axelor-gradle/src/main/groovy/com/axelor/tools/x2j/pojo/Property.groovy
+++ b/axelor-gradle/src/main/groovy/com/axelor/tools/x2j/pojo/Property.groovy
@@ -643,6 +643,11 @@
.add("translatable", translatable, false)
.add("copyable", copyable, false)
.add("defaultNow", defaultNow ? "true" : null, false)
+
+ // add LARGE annotation if field is an encrypted string with the 'large' attribute sets to true
+ if (type == "string" && isEncrypted() && isLarge()) {
+ annon("com.axelor.db.annotations.Widget").add("large", "true", false);
+ }
}
private List<Annotation> $binary() {
@@ -662,10 +667,21 @@
}
if (isLarge() && type == 'string') {
+ // use annotation type only for non encrypted columns (type & converter cannot be specified together
+ if(!isEncrypted()) {
+ return [
+ annon("javax.persistence.Lob", true),
+ annon("javax.persistence.Basic").add("fetch", "javax.persistence.FetchType.LAZY", false),
+ annon("org.hibernate.annotations.Type").add("type", "text")
+ ]
+ }
+ }
+
+ // is string is an encrypted on (whatever large or not), set it to LOB
+ if (isEncrypted() && type == 'string') {
return [
annon("javax.persistence.Lob", true),
annon("javax.persistence.Basic").add("fetch", "javax.persistence.FetchType.LAZY", false),
- annon("org.hibernate.annotations.Type").add("type", "text")
]
}
This patch is to manage the ‘large’ widget
diff --git a/axelor-core/src/main/java/com/axelor/db/annotations/Widget.java b/axelor-core/src/main/java/com/axelor/db/annotations/Widget.java
index c9aec6c..ab54fdb 100644
--- a/axelor-core/src/main/java/com/axelor/db/annotations/Widget.java
+++ b/axelor-core/src/main/java/com/axelor/db/annotations/Widget.java
@@ -127,4 +127,11 @@
* @return name of the selection, default is empty
*/
String selection() default "";
+
+ /**
+ * To know if the field is a large one or not (used for String and especially for encrypted one
+ * to set a default widget as TEXT to have a multiline input
+ * @return
+ */
+ boolean large() default false;
}
\ No newline at end of file
This patch is to force the UI to take the encrypted string (TEXT datatype) not as a large string but a single one. The problem here is that the “large” attribute is not taken in consideration. To be able to have a multiline encrypted string the “text” widget need to be explicitly added in the form field.
diff --git a/axelor-web/src/main/webapp/js/view/view.form.js b/axelor-web/src/main/webapp/js/view/view.form.js
index 6210399..9e14de1 100644
--- a/axelor-web/src/main/webapp/js/view/view.form.js
+++ b/axelor-web/src/main/webapp/js/view/view.form.js
@@ -1206,6 +1206,13 @@
if (type == 'label') {
type = 'static-label';
}
+
+ // set field as String if is an encrypted
+ if(type == 'text' && attrs.encrypted) {
+ if(widget == null || widget != "text") {
+ type = "string"
+ }
+ }
if (attrs.type == 'panel-related') {
type = 'panel-' + (field.type || attrs.serverType || type);
This is the patch for encryptor: user 16 bytes IV for all modes (truncated internally with CGM) and PBKDF2WithHmacSHA256 as key algo.
diff --git a/axelor-common/src/main/java/com/axelor/common/crypto/BytesEncryptor.java b/axelor-common/src/main/java/com/axelor/common/crypto/BytesEncryptor.java
index 8b7deb1..15beed0 100644
--- a/axelor-common/src/main/java/com/axelor/common/crypto/BytesEncryptor.java
+++ b/axelor-common/src/main/java/com/axelor/common/crypto/BytesEncryptor.java
@@ -36,7 +36,7 @@
public class BytesEncryptor implements Encryptor<byte[], byte[]> {
private static final String AES_ALGORITHM = "AES";
- private static final String KEY_ALGORITHM = "PBKDF2WithHmacSHA1";
+ private static final String KEY_ALGORITHM = "PBKDF2WithHmacSHA256";
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
@@ -62,9 +62,7 @@
this.transformation = String.format("%s/%s/%s", AES_ALGORITHM, mode, paddingScheme);
this.encryptionSalt = generateRandomBytes(SALT_SIZE);
this.encryptionKey = newSecretKey(password, this.encryptionSalt);
- this.payloadSize = mode == OperationMode.CBC
- ? PREFIX_BYTES.length + SALT_SIZE
- : PREFIX_BYTES.length + SALT_SIZE + IV_SIZE;
+ this.payloadSize = PREFIX_BYTES.length + SALT_SIZE + IV_SIZE;
}
public BytesEncryptor(String password) {
@@ -139,13 +137,11 @@
return bytes;
}
- final byte[] iv = this.mode == OperationMode.CBC ? new byte[IV_SIZE] : generateRandomBytes(IV_SIZE);
+ final byte[] iv = generateRandomBytes(IV_SIZE);
final Cipher cipher = newCipher(Cipher.ENCRYPT_MODE, this.encryptionKey, iv);
final byte[] encrypted = doFinal(cipher, bytes);
- return this.mode == OperationMode.CBC
- ? Bytes.concat(PREFIX_BYTES, this.encryptionSalt, encrypted)
- : Bytes.concat(PREFIX_BYTES, this.encryptionSalt, iv, encrypted);
+ return Bytes.concat(PREFIX_BYTES, this.encryptionSalt, iv, encrypted);
}
@Override
@@ -158,9 +154,7 @@
final byte[] iv = new byte[IV_SIZE];
final byte[] data = new byte[bytes.length - this.payloadSize];
- final List<byte[]> sections = this.mode == OperationMode.CBC
- ? Arrays.asList(salt, data)
- : Arrays.asList(salt, iv, data);
+ final List<byte[]> sections = Arrays.asList(salt, iv, data);
int index = PREFIX_BYTES.length;
for (byte[] section : sections) {
This is the patch to manage correct type on the UI
diff --git a/axelor-web/src/main/webapp/js/view/view.form.js b/axelor-web/src/main/webapp/js/view/view.form.js
index 6210399..246ed85 100644
--- a/axelor-web/src/main/webapp/js/view/view.form.js
+++ b/axelor-web/src/main/webapp/js/view/view.form.js
@@ -1206,6 +1206,11 @@
if (type == 'label') {
type = 'static-label';
}
+
+ // set field as String if is an encrypted and not large
+ if(type == 'text' && attrs.encrypted) {
+ if(attrs.large == null || !attrs.large) type = "string"
+ }
if (attrs.type == 'panel-related') {
type = 'panel-' + (field.type || attrs.serverType || type);
Moreover,I think you need to add a special explanation inside the documentation for encrypted field due to Java Security Policy that is restricted by default with Oracle JRE (Java Cryptography Extension Unlimited Strength Jurisdiction Policy).
Now this kind of fields are working:
<string name="encrypted_single" min="5" max="20" encrypted="true"/>
<string name="encrypted_large" encrypted="true" large="true" />
Hope it help you to improve encrypted fields necanism.
Regards