CertificateProfileData is one of the old classes that uses Serialized binary data in a blob in the database. In order for CertificateProfileData.getProtectString to produce a String the object is read in and then the getData() method returns a LinkedHashMap. StringBuilder.build() calls toString() on the LinkedHashMap, which in turn calls toString() on the objects in it. One of the objects is a ApprovalRequestType. In
ECA-6518 the toString() method was overridden in this enum, causing the string representation to be different. This causes rowProtection signature verification to fail if you upgrade from a version <=6.11 to a version >=6.12.
Good news is that the data stored in the database is the same between versions, it is only the string used for verification that differs due to the running code.
See the attached images for a brain storming session going through the issue.
The suggested solution is:
- Revert in 6.14.2 to use the old (correct) toString() for ApprovalRequestType. Use toReadableString() to get the nice readable string value instead of overriding toString().
- Override verify in CertificateProfileData to catch verification exception and try with the 6.12-6.14 protectString, replacing values in the string. If verification still fails, throw the original exception
- Fix YAML export to use getReadableString for ApprovalRequestType instead, so YAML export still is the same, with the nice looking string.
- Create a JUnit (standalone) test of signature verification for CertificateProfileData, with a known 6.11 data and a known 6.11 protectString, and a known 6.12 data and 6.12 protectString
A factor limiting the effect of the change is that only EJBCA installation done with a version 6.12 or later, and using full database integrity protection, is impacted.
Long term, create follow up tickets for EJBCA 7 when this issue is resolved:
- Convert the blob object signatures to use raw blob data instead of toString. This will be safe against any changes in string representation for all eternity. Make a new protectStringVersion for the new protect method (getProtectString(int version))
- Add JUnit tests for rowProtection for all database objects with known data and expected result/verification
- Make a post-upgrade in EJBCA 7 that converts old blob object to use the new raw database protection string (post-upgrade is needed in order to keep 100% uptime cluster upgrades)
- Add "known earlier versions" to global configuration when EJBCA has been upgraded to a new version, so for any installation we can backtrack all versions it has been upgraded through.