src/main/java/org/imsglobal/lti/BasicLTIUtil.java
public static String mapKeyName(String keyname) {
        StringBuffer sb = new StringBuffer();
        if (keyname == null) {
            return null;
        }
        keyname = keyname.trim();
        if (keyname.length() < 1) {
            return null;
        }
        for (int i = 0; i < keyname.length(); i++) {
            Character ch = Character.toLowerCase(keyname.charAt(i));
            if (Character.isLetter(ch) || Character.isDigit(ch)) {
                sb.append(ch);
            } else {
                sb.append('_');
            }
        }
        return sb.toString();
    }
public static String mapKeyName(String keyname) {
        StringBuffer sb = new StringBuffer();
        if (keyname == null) {
            return null;
        }
        keyname = keyname.trim();
        if (keyname.length() < 1) {
            return null;
        }
        for (int i = 0; i < keyname.length(); i++) {
            Character ch = Character.toLowerCase(keyname.charAt(i));
            if (Character.isLetter(ch) || Character.isDigit(ch)) {
                sb.append(ch);
            } else {
                sb.append('_');
            }
        }
        return sb.toString();
    }
The parameter name is mapped to lower case and any character that is
neither a number or letter is replaced with an "underscore". So if a
custom entry was as follows:

{@code <parameter name="Vendor:Chapter">1.2.56</parameter>}

Would map to: custom_vendor_chapter=1.2.56