{"record":{"id":"5fa64298647a573f","repo":"grpc/grpc-java","slug":"decrypt-is-not-supported","errorCode":null,"errorMessage":"decrypt is not supported.","messagePattern":"decrypt is not supported\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2APrivateKeyMethod.java","lineNumber":145,"sourceCode":"    }\n\n    SessionResp resp = stub.send(reqBuilder.build());\n\n    if (resp.hasStatus() && resp.getStatus().getCode() != 0) {\n      throw new S2AConnectionException(\n          String.format(\n              \"Error occurred in response from S2A, error code: %d, error message: \\\"%s\\\".\",\n              resp.getStatus().getCode(), resp.getStatus().getDetails()));\n    }\n    if (!resp.hasOffloadPrivateKeyOperationResp()) {\n      throw new S2AConnectionException(\"No valid response received from S2A.\");\n    }\n    return resp.getOffloadPrivateKeyOperationResp().getOutBytes().toByteArray();\n  }\n\n  @Override\n  public byte[] decrypt(SSLEngine engine, byte[] input) {\n    throw new UnsupportedOperationException(\"decrypt is not supported.\");\n  }\n}","sourceCodeStart":127,"sourceCodeEnd":147,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2APrivateKeyMethod.java#L127-L147","documentation":"S2APrivateKeyMethod implements a private-key method for the S2A handshaker but only supports signing operations. The decrypt() method is unconditionally unsupported and always throws UnsupportedOperationException when the TLS stack attempts to offload a decryption operation to the S2A. This is a deliberate design boundary, not a transient failure.","triggerScenarios":"Calling S2APrivateKeyMethod.decrypt(SSLEngine, byte[]) directly, or using this private-key method with a TLS cipher suite/protocol flow that requires RSA key exchange ( decryption ) instead of signature-based ( e.g. ECDHE ) handshakes.","commonSituations":"Configuring a server socket with S2A offload while negotiating a legacy static-RSA cipher suite; custom code invoking decrypt() on the private key method; older clients that only support static RSA key exchange connecting to an S2A-offloaded endpoint.","solutions":["Use an ephemeral key-exchange cipher suite ( ECDHE/DHE ) so the handshake uses signatures rather than decryption.","Restrict enabled cipher suites ( e.g. via SslContextBuilder ) to exclude static RSA key exchange.","If decryption offload is required, use a different private-key method implementation that supports it."],"exampleFix":"// before\nsslContextBuilder.ciphers(Arrays.asList(\"TLS_RSA_WITH_AES_128_GCM_SHA256\"));\n// after\nsslContextBuilder.ciphers(Arrays.asList(\"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\"));","handlingStrategy":"validation","validationCode":"if (cipherSuite.startsWith(\"TLS_RSA_\")) {\n  throw new IllegalArgumentException(\"Static RSA key exchange unsupported with S2A offload; use ECDHE suites\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  keyMethod.decrypt(engine, input);\n} catch (UnsupportedOperationException e) {\n  // fall back to local key or reject handshake\n}","preventionTips":["Only enable signature-based ( ECDHE/DHE ) cipher suites with S2A offload.","Never call decrypt() on S2APrivateKeyMethod directly; rely on sign operations.","Document the supported operation set of the private-key method in your TLS setup code."],"tags":["unsupported-operation","tls","grpc","s2a"],"backgroundTag":"unsupported-operation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}