{"record":{"id":"5fd48424bc5ab18f","repo":"apache/hadoop","slug":"invalid-transformation-format-transformation","errorCode":null,"errorMessage":"Invalid transformation format: ${transformation}","messagePattern":"Invalid transformation format: (.+?)","errorType":"exception","errorClass":"NoSuchAlgorithmException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/OpensslCipher.java","lineNumber":175,"sourceCode":"    if (transformation == null) {\n      throw new NoSuchAlgorithmException(\"No transformation given.\");\n    }\n    \n    /*\n     * Array containing the components of a Cipher transformation:\n     * \n     * index 0: algorithm (e.g., AES)\n     * index 1: mode (e.g., CTR)\n     * index 2: padding (e.g., NoPadding)\n     */\n    String[] parts = new String[3];\n    int count = 0;\n    StringTokenizer parser = new StringTokenizer(transformation, \"/\");\n    while (parser.hasMoreTokens() && count < 3) {\n      parts[count++] = parser.nextToken().trim();\n    }\n    if (count != 3 || parser.hasMoreTokens()) {\n      throw new NoSuchAlgorithmException(\"Invalid transformation format: \" + \n          transformation);\n    }\n    return new Transform(parts[0], parts[1], parts[2]);\n  }\n\n  public static boolean isSupported(CipherSuite suite) {\n    Transform transform;\n    int algMode;\n    int padding;\n    try {\n      transform = tokenizeTransformation(suite.getName());\n      algMode = AlgMode.get(transform.alg, transform.mode);\n      padding = Padding.get(transform.padding);\n    } catch (NoSuchAlgorithmException|NoSuchPaddingException e) {\n      return false;\n    }\n    return isSupportedSuite(algMode, padding);\n  }","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/OpensslCipher.java#L157-L193","documentation":"The transformation must consist of exactly three slash-separated tokens: algorithm, mode, and padding. tokenizeTransformation() tokenizes on '/', collects at most three parts, and throws NoSuchAlgorithmException when the count is not exactly 3 (including when more than 3 tokens remain).","triggerScenarios":"Calling OpensslCipher.getInstance() with malformed strings: \"AES\" (1 token), \"AES/CTR\" (2 tokens), \"AES/CTR/NoPadding/Extra\" (4 tokens), or strings with empty or extra separators such as \"AES//NoPadding\" or \"/AES/CTR/NoPadding\" — empty tokens count as tokens, producing wrong counts or later enum failures.","commonSituations":"String concatenation bugs when assembling the transformation at runtime; config values with stray slashes or trailing whitespace plus a slash; user-typed suite names in configuration files.","solutions":["Always use the canonical three-part form, ideally sourced from CipherSuite.getName() (e.g. AES/CTR/NoPadding)","Validate the transformation format before use: exactly two '/' characters and three non-empty trimmed tokens","Reject the configuration at load time with a clear error instead of passing it downstream"],"exampleFix":"// before\nString t = alg + \"/\" + mode + \"/\" + padding; // padding empty -> \"AES/CTR/\"\nCipher c = OpensslCipher.getInstance(t); // Invalid transformation format\n\n// after\nString t = String.join(\"/\", alg, mode, padding);\n Preconditions.checkArgument(t.split(\"/\").length == 3, \"bad suite %s\", t);\nCipher c = OpensslCipher.getInstance(t);","handlingStrategy":"validation","validationCode":"// Structural pre-check\nString[] p = transformation.split(\"/\");\nif (p.length != 3 || Arrays.stream(p).anyMatch(String::isEmpty)) {\n  throw new IllegalArgumentException(\n    \"Transformation must be alg/mode/padding, got: \" + transformation);\n}","typeGuard":"private static final Pattern T = Pattern.compile(\"^(AES|SM4)/(CTR)/(NoPadding)$\");\npublic boolean isWellFormedTransformation(String t) {\n  return t != null && T.matcher(t).matches();\n}","tryCatchPattern":"try {\n  cipher = OpensslCipher.getInstance(transformation);\n} catch (NoSuchAlgorithmException e) {\n  throw new ConfigurationException(\"Malformed cipher transformation: '\" + transformation + \"'\", e);\n}","preventionTips":["Build transformations with String.join over explicit components, never concatenation with optional parts","Validate suite config at load time (exactly two slashes, three non-empty tokens)","Use the regex/enum approach so typos fail at configuration parse, not at cipher creation"],"tags":["crypto","openssl","transformation","input-validation"],"backgroundTag":"invalid-cipher-transformation","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}