{"id":24481373,"url":"https://github.com/wsargent/ocapjsse","last_synced_at":"2025-10-28T17:31:59.986Z","repository":{"id":102465709,"uuid":"146687198","full_name":"wsargent/ocapjsse","owner":"wsargent","description":"Object Capability Enabled JSSE classes","archived":false,"fork":false,"pushed_at":"2018-10-21T04:28:10.000Z","size":60,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-14T18:42:29.575Z","etag":null,"topics":["capabilities","java","jsse","logging","ocap","revocation","security"],"latest_commit_sha":null,"homepage":"https://tersesystems.com/blog/2018/10/20/jsse-with-object-capabilities/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wsargent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-30T02:51:08.000Z","updated_at":"2024-12-31T02:54:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"def48307-06c1-428c-b414-7cc5590a3673","html_url":"https://github.com/wsargent/ocapjsse","commit_stats":null,"previous_names":["wsargent/ocapjsse"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/wsargent/ocapjsse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wsargent%2Focapjsse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wsargent%2Focapjsse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wsargent%2Focapjsse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wsargent%2Focapjsse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wsargent","download_url":"https://codeload.github.com/wsargent/ocapjsse/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wsargent%2Focapjsse/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263606581,"owners_count":23487660,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["capabilities","java","jsse","logging","ocap","revocation","security"],"created_at":"2025-01-21T11:41:36.502Z","updated_at":"2025-10-28T17:31:59.863Z","avatar_url":"https://github.com/wsargent.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Object Capability (OCAP) Enabled JSSE\n\nThis is a small library that provides proxies for JSSE based classes such as `SSLEngine`, `KeyManager` and `TrustManager`, and provides facilities to decorate behavior with logging and revocation.\n\n## Construction\n\nObject capabilities are based around deferred execution and composition, so that instead of dealing with a direct object reference, you deal with a proxy that manages your access to the object.  \n\nProxies are very simple to set up.  You define a supplier, and then you delegate all access through resolving that supplier.  Here's an example of X509ExtendedKeyManager set up with a proxy:\n\n```java\npackage com.tersesystems.ocapjsse;\n\npublic class ProxyX509ExtendedKeyManager extends X509ExtendedKeyManager {\n\n  protected Supplier\u003cX509ExtendedKeyManager\u003e supplier;\n\n  public ProxyX509ExtendedKeyManager(Supplier\u003cX509ExtendedKeyManager\u003e supplier) {\n    Objects.requireNonNull(supplier);\n    this.supplier = supplier;\n  }\n\n  public String chooseEngineClientAlias(\n      final String[] keyTypes, final Principal[] issuers, final SSLEngine engine) {\n    return supplier.get().chooseEngineClientAlias(keyTypes, issuers, engine);\n  }\n  \n  // ...\n}\n```\n\n### Logging\n\nOnce you have a proxy, you can then set up logging around the manager: \n\n```java\npackage com.tersesystems.ocapjsse.revocable;\n\npublic class LoggingX509ExtendedTrustManager extends ProxyX509ExtendedTrustManager {\n  private final TraceLogger tracer;\n\n  public LoggingX509ExtendedTrustManager(\n      final Supplier\u003cX509ExtendedTrustManager\u003e supplier, final TraceLogger tracer) {\n    super(supplier);\n    this.tracer = tracer;\n  }\n\n  @Override\n  public void checkClientTrusted(final X509Certificate[] chain, final String authType,\n      final Socket socket)\n      throws CertificateException {\n    final Object[] params = {chain, authType, socket};\n    tracer.apply(\n        \"checkClientTrusted\", params, () -\u003e super.checkClientTrusted(chain, authType, socket));\n  }\n  \n  // ...\n}\n```\n\nThis is a lightweight alternative to using the [debugjsse provider](https://github.com/tersesystems/debugjsse), as you can restrict logging to only a single trust manager.\n\n```java\npublic class LoggingX509ExtendedTrustManagerTest {\n\n  @Test\n  public void testLog() throws Exception {\n    final TraceLogger tracer =\n        new AbstractTraceLogger() {\n          @Override\n          protected void entry(final String methodName, final Object... parameters) {\n            System.out.println(\"entry: \" + methodName);\n          }\n\n          @Override\n          protected \u003cR\u003e R exit(final R result, final String methodName,\n              final Object... parameters) {\n            System.out.println(\"exit: \" + methodName);\n            return result;\n          }\n\n          @Override\n          protected void exit(final String methodName, final Object... parameters) {\n            System.out.println(\"exit: \" + methodName);\n          }\n\n          @Override\n          protected void exception(final Throwable e, final String methodName,\n              final Object... parameters) {\n            System.out.println(\"exception: \" + methodName);\n          }\n        };\n\n    try {\n      final SSLContext sslContext = SSLContext.getInstance(\"TLS\");\n      final TrustManagerFactory tmf =\n          TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());\n      tmf.init((KeyStore) null);\n      final TrustManager[] tms =\n          Arrays.stream(tmf.getTrustManagers())\n              .map(LoggingX509ExtendedTrustManager.transform(tracer))\n              .toArray(TrustManager[]::new);\n\n      sslContext.init(null, tms, null);\n      final HttpsURLConnection urlConnection =\n          (HttpsURLConnection) new URL(\"https://www.google.com\").openConnection();\n      urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());\n\n      // Call Google\n      try (final BufferedReader in =\n          new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) {\n        final String result = in.lines().collect(Collectors.joining());\n        System.out.println(result);\n      }\n    } catch (final Exception e) {\n      e.printStackTrace();\n    }\n  }\n}\n```\n\n### Revocation\n\nYou can even use a caretaker to set up revocation.  This can be used to break off communication immediately when a security guarantee is violated, or to enforce a time limit on access.\n\n```java\npackage com.tersesystems.ocapjsse.revocable;\n\npublic class RevocableTrustManagerTest {\n  @Test\n  public void testRevokedEngine() throws Exception {\n    X509ExtendedTrustManager trustManager = createTrustManager();\n    assertThat(trustManager).isNotNull();\n\n    Caretaker\u003cX509ExtendedTrustManager\u003e caretaker = Caretaker\n        .create(trustManager, ProxyX509ExtendedTrustManager::new);\n    X509ExtendedTrustManager proxyTrustManager = caretaker.getCapability();\n\n    X509Certificate[] issuers = proxyTrustManager.getAcceptedIssuers();\n    assertThat(issuers).isNotNull();\n    caretaker.getRevoker().revoke();\n\n    Throwable throwable = catchThrowable(proxyTrustManager::getAcceptedIssuers);\n    assertThat(throwable).isInstanceOf(RevokedException.class);\n  }\n}\n```\n\nFor more about revocation, see [managing accessibility with revocation](https://wsargent.github.io/ocaps/guide/management.html#managing-accessibility-with-revocation).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwsargent%2Focapjsse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwsargent%2Focapjsse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwsargent%2Focapjsse/lists"}