Closed kukel closed 4 years ago
Sorry, no PC at hand to create a PR, so a working piece of code is here: Might need some optimization coding rules wise
private static final String _upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String _lower = _upper.toLowerCase(Locale.ROOT);
private static final String _digits = "0123456789";
private static final String _symbols = "@#$%()[]{}*^-!~|+=";
/**
* @return A new random migration key with at last 24 characters and in line with SML requirements
* must contain
* a minimum of 8 characters
* - 2 Upper Case letters
* - 2 Lower Case letters
* - 2 Special Characters among @#$%()[]{}*^-!~|+=
* - 2 numbers)
* a maximum of 24 characters
* No White Spaces.
*/
@Nonnull
@Nonempty
public static final String createRandomMigrationKey ()
{
Random rand = new SecureRandom();
String upper = nextString(2, rand, _upper);
String lower = nextString(2, rand, _lower);
String number = nextString(2, rand, _digits);
String symbols = nextString(2, rand, _symbols);
String other = nextString(16, rand, _upper+_lower+_digits+_symbols); //Add 16 randomly from the complete set to get to 24
String sKey = (upper+lower+number+symbols+other);
List<Character> key = sKey.chars().mapToObj(c -> (char) c).collect(Collectors.toList()); // String to List<Character> for shuffle
Collections.shuffle(key, rand); // Shuffle so all characters are in a random order
sKey = key.stream().map(String::valueOf).collect(Collectors.joining()); // List<Character> to String
return getSuitableMigrationKey (sKey);
}
/** Creates String of length 'length' from the set of 'charSet' and uses the provided 'random'
*
* @param length
* @param random
* @param charSet
* @return
*/
private static String nextString(int length, Random random, String charSet) {
final char[] buf = new char[length];
char[] chars = charSet.toCharArray();
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = chars[random.nextInt(chars.length)];
return new String(buf);
}
That is the underlying regex in BDMSL 4.0.2:
public static final String MIGRATION_KEY_REGEX = "^(?=.{8,24}$)(?=(.*[@#$%()\\[\\]{}*^_\\-!~|+=]){2,})(?=(.*[A-Z]){2})(?=(.*[a-z]){2})(?=(.*[0-9]){2})(?=\\S+$).*$";
According to the Peppol SML specification, this is required:
The SMP generates a Migration Key which is a unique string containing characters and numbers only, with a maximum length of 24 characters. The original SMP invokes the PrepareToMigrate operation of the SML and then passes the migration key to the new SMP (the key passing is an out-of-band step not defined in these specifications).
So we're in breach of the spec here - I will contact CEF/Peppol and try to find a solution
I have created PEPPOL-2865 for this
Is this publically visible somewhere? Cannot seem to find a (jira?) issuelist
No, unfortunately not - I will keep you posted (takes some time anyway)
Clean work around for now: provide an external migration key. Better fix comes later. I am leaving this issue open.
Peppol CMB acknowledged the issue, and will update their SML implementation to reflect the requirements of the BDMSL implementation by CEF.
Part of the 8.1.2 release
Version: 8.1.2-SNAPSHOT
The error I receive when doing:
I'll see if I cant create a PR so it peppol-commons conforms with this. Weird...
Off-topic: In the method signature for the prepareToMigrate and migrate the parameters are reversed compared to the other methods. Intentional?