{"id":37024095,"url":"https://github.com/gini/jersey-smime","last_synced_at":"2026-01-14T02:54:30.365Z","repository":{"id":10437882,"uuid":"12603262","full_name":"gini/jersey-smime","owner":"gini","description":"A port of the S/MIME implementation in resteasy-crypto to Jersey","archived":true,"fork":false,"pushed_at":"2016-01-14T17:10:10.000Z","size":752,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-14T00:59:10.742Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://developer.gini.net/jersey-smime/0.3.0/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gini.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"License.html","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-09-04T22:10:32.000Z","updated_at":"2023-01-28T08:54:20.000Z","dependencies_parsed_at":"2022-07-30T11:18:04.403Z","dependency_job_id":null,"html_url":"https://github.com/gini/jersey-smime","commit_stats":null,"previous_names":["joschi/jersey-smime"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/gini/jersey-smime","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gini%2Fjersey-smime","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gini%2Fjersey-smime/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gini%2Fjersey-smime/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gini%2Fjersey-smime/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gini","download_url":"https://codeload.github.com/gini/jersey-smime/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gini%2Fjersey-smime/sbom","scorecard":{"id":427271,"data":{"date":"2025-08-11","repo":{"name":"github.com/gini/jersey-smime","commit":"13e22d4a5772eb4080bd4b4bb1de555566184a10"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":0,"reason":"Found 1/21 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: License.html:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-jw7r-rxff-gv24","Warn: Project is vulnerable to: GHSA-4cx2-fc23-5wg6","Warn: Project is vulnerable to: GHSA-6xx3-rg99-gc3p","Warn: Project is vulnerable to: GHSA-72m5-fvvv-55m6","Warn: Project is vulnerable to: GHSA-8xfc-gm6g-vgpv","Warn: Project is vulnerable to: GHSA-hr8g-6v94-x4m9","Warn: Project is vulnerable to: GHSA-v435-xc8x-wvr9","Warn: Project is vulnerable to: GHSA-wjxj-5m7g-mg7q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T02:30:11.617Z","repository_id":10437882,"created_at":"2025-08-19T02:30:11.617Z","updated_at":"2025-08-19T02:30:11.617Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2026-01-14T02:54:29.677Z","updated_at":"2026-01-14T02:54:30.358Z","avatar_url":"https://github.com/gini.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Jersey S/MIME #\n\n[![Build Status](https://secure.travis-ci.org/gini/jersey-smime.png?branch=master)](https://travis-ci.org/gini/jersey-smime)\n[![Coverage Status](https://img.shields.io/coveralls/gini/jersey-smime.svg)](https://coveralls.io/r/gini/jersey-smime)\n\nJersey S/MIME is a port of the S/MIME functionality in `resteasy-security` to the Jersey framework.\n\nS/MIME (Secure/Multipurpose Internet Mail Extensions) is a standard for public key encryption and signing of MIME data. MIME data being a set of headers and a message body. It's most often seen in the email world when somebody wants to encrypt and/or sign an email message they are sending across the Internet. It can also be used for HTTP requests as well which is what the Jersey integration with S/MIME is all about. Jersey S/MIME allows you to easily encrypt and/or sign an email message using the S/MIME standard.\n\n\n## Maven Artifacts ##\n\nYou must include the jersey-crypto project to use the S/MIME framework.\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003enet.gini\u003c/groupId\u003e\n        \u003cartifactId\u003ejersey-smime\u003c/artifactId\u003e\n        \u003cversion\u003e0.3.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\n\n## Usage ##\n\n### Message Body Encryption ###\n\nWhile HTTPS is used to encrypt the entire HTTP message, S/MIME encryption is used solely for the message body of the HTTP request or response. This is very useful if you have a representation that may be forwarded by multiple parties and you want to protect the message from prying eyes as it travels across the network. Jersey S/MIME has two different interfaces for encrypting message bodies. One for output, one for input. If your client or server wants to send an HTTP request or response with an encrypted body, it uses the `net.gini.jersey.security.smime.EnvelopedOutput` type. Encrypting a body also requires an X509 certificate which can be generated by the Java `keytool` command-line interface, or the `openssl` tool that comes installed on many OS's.\n\nHere's an example of using the `EnvelopedOutput` interface:\n\n    // server side   \n    \n    @Path(\"encrypted\")\n    @GET\n    public EnvelopedOutput getEncrypted() {\n       Customer cust = new Customer();\n       cust.setName(\"Bill\");\n       \n       X509Certificate certificate = ...;\n       EnvelopedOutput output = new EnvelopedOutput(cust, MediaType.APPLICATION_XML_TYPE);\n       output.setCertificate(certificate);\n       return output;\n    }\n\n\n    // client side\n    \n    Client client = ClientBuilder.newClient();\n    X509Certificate cert = ...; \n    Customer cust = new Customer();\n    cust.setName(\"Bill\");\n    EnvelopedOutput output = new EnvelopedOutput(cust, \"application/xml\");\n    output.setCertificate(cert);\n    Response res = client.target(\"http://localhost:9095/smime/encrypted\").request().post(Entity.entity(output, \"application/pkcs7-mime\"));\n\nAn `EnvelopedOutput` instance is created passing in the entity you want to marshal and the media type you want to marshal it into. So in this example, we're taking a Customer class and marshalling it into XML before we encrypt it. Jersey will then encrypt the `EnvelopedOutput` using the BouncyCastle framework's S/MIME integration. The output is a Base64 encoding and would look something like this:\n\n    Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\"\n    Content-Transfer-Encoding: base64\n    Content-Disposition: attachment; filename=\"smime.p7m\"\n    \n    MIAGCSqGSIb3DQEHA6CAMIACAQAxgewwgekCAQAwUjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMK\n    U29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkAgkA7oW81OriflAw\n    DQYJKoZIhvcNAQEBBQAEgYCfnqPK/O34DFl2p2zm+xZQ6R+94BqZHdtEWQN2evrcgtAng+f2ltIL\n    xr/PiK+8bE8wDO5GuCg+k92uYp2rLKlZ5BxCGb8tRM4kYC9sHbH2dPaqzUBhMxjgWdMCX6Q7E130\n    u9MdGcP74Ogwj8fNl3lD4sx/0k02/QwgaukeY7uNHzCABgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcE\n    CDRozFLsPnSgoIAEQHmqjSKAWlQbuGQL9w4nKw4l+44WgTjKf7mGWZvYY8tOCcdmhDxRSM1Ly682\n    Imt+LTZf0LXzuFGTsCGOUo742N8AAAAAAAAAAAAA\n\nDecrypting an S/MIME encrypted message requires using the `net.gini.jersey.security.smime.EnvelopedInput` interface. You also need both the private key and `X509Certificate` used to encrypt the message. Here's an example:\n\n    // server side\n    \n    @Path(\"encrypted\")\n    @POST\n    public void postEncrypted(EnvelopedInput\u003cCustomer\u003e input) {\n        PrivateKey privateKey = ...;\n        X509Certificate certificate = ...;\n        Customer cust = input.getEntity(privateKey, certificate);\n    }\n\n\n    // client side\n    \n    Client client = ClientBuilder.newClient();\n    Response response = client.target(\"http://localhost:9095/smime/encrypted\").request().get();\n    EnvelopedInput input = response.readEntity(EnvelopedInput.class);\n    Customer cust = (Customer)input.getEntity(Customer.class, privateKey, cert);\n\nBoth examples simply call the `getEntity()` method passing in the `PrivateKey` and `X509Certificate` instances requires to decrypt the message. On the server side, a generic is used with `EnvelopedInput` to specify the type to marshal to. On the server side this information is passed as a parameter to `getEntity()`. The message is in MIME format: a `Content-Type` header and body, so the `EnvelopedInput` class now has everything it needs to know to both decrypt and unmarshall the entity.\n\n\n### Message Body Signing ###\n\nS/MIME also allows you to digitally sign a message. It uses the `multipart/signed` data format which is a multipart message that contains the entity and the digital signature.\n\nJersey S/MIME has two different interfaces for creating a `multipart/signed` message. One for input, one for output. If your client or server wants to send an HTTP request or response with an `multipart/signed` body, it uses the `net.gini.jersey.security.smime.SignedOutput` type. This type requires both the `PrivateKey` and `X509Certificate` to create the signature. Here's an example of signing an entity and sending a `multipart/signed` entity.\n\n    // server-side\n     \n    @Path(\"signed\")\n    @GET\n    public SignedOutput getSigned() {\n        Customer cust = new Customer();\n        cust.setName(\"Bill\");\n    \n        SignedOutput output = new SignedOutput(cust, MediaType.APPLICATION_XML_TYPE);\n        output.setPrivateKey(privateKey);\n        output.setCertificate(certificate);\n        return output;\n    }\n\n\n    // client side\n     \n    Client client = ClientBuilder.newClient();\n    Customer cust = new Customer();\n    cust.setName(\"Bill\");\n    SignedOutput output = new SignedOutput(cust, \"application/xml\");\n    output.setPrivateKey(privateKey);\n    output.setCertificate(cert);\n    Response res = client.target(\"http://localhost:9095/smime/signed\").request().post(Entity.entity(output, \"multipart/signed\"));\n\n\nAn `SignedOutput` instance is created passing in the entity you want to marshal and the media type you want to marshal it into. So in this example, we're taking a `Customer` class and marshalling it into XML before we sign it. Jersey will then sign the `SignedOutput` using the BouncyCastle framework's S/MIME integration. The output would look something like this:\n\n    Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1;  boundary=\"----=_Part_0_1083228271.1313024422098\"\n    \n    ------=_Part_0_1083228271.1313024422098\n    Content-Type: application/xml\n    Content-Transfer-Encoding: 7bit\n    \n    \u003ccustomer name=\"bill\"/\u003e\n    ------=_Part_0_1083228271.1313024422098\n    Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data\n    Content-Transfer-Encoding: base64\n    Content-Disposition: attachment; filename=\"smime.p7s\"\n    Content-Description: S/MIME Cryptographic Signature\n    \n    MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAMYIBVzCCAVMC\n    AQEwUjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu\n    ZXQgV2lkZ2l0cyBQdHkgTHRkAgkA7oW81OriflAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzEL\n    BgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTExMDgxMTAxMDAyMlowIwYJKoZIhvcNAQkEMRYE\n    FH32BfR1l1vzDshtQvJrgvpGvjADMA0GCSqGSIb3DQEBAQUABIGAL3KVi3ul9cPRUMYcGgQmWtsZ\n    0bLbAldO+okrt8mQ87SrUv2LGkIJbEhGHsOlsgSU80/YumP+Q4lYsVanVfoI8GgQH3Iztp+Rce2c\n    y42f86ZypE7ueynI4HTPNHfr78EpyKGzWuZHW4yMo70LpXhk5RqfM9a/n4TEa9QuTU76atAAAAAA\n    AAA=\n    ------=_Part_0_1083228271.1313024422098--\n\n\nTo unmarshal and verify a signed message requires using the `net.gini.jersey.security.smime.SignedInput` interface. You only need the `X509Certificate` to verify the message. Here's an example of unmarshalling and verifying a `multipart/signed` entity.\n\n    // server side\n\n    @Path(\"signed\")\n    @POST\n    public void postSigned(SignedInput\u003cCustomer\u003e input) throws Exception {\n        Customer cust = input.getEntity();\n        if (!input.verify(certificate)) {\n           throw new WebApplicationException(500);\n        }\n    }\n\n\n    // client side\n    \n    Client client = ClientBuilder.newClient();\n    Response response = client.target(\"http://localhost:9095/smime/signed\").request().get();\n    SignedInput input = response.readEntity(SignedInput.class);\n    Customer cust = (Customer)input.getEntity(Customer.class)\n    input.verify(cert);\n\n## Testing ##\n\n## Warning ##\n\nBe aware of using other than default Connector implementation. There is an issue handling HTTP headers in ``WriterInterceptor` or `MessageBodyWriter\u003cT\u003e`. If you need to change header fields do not use nor ApacheConnectorProvider nor GrizzlyConnectorProvider neither JettyConnectorProvider.\nOn the other hand, in the default transport connector, there are some restrictions on the headers, that can be sent in the default configuration.\nSince the S/MIME protocol depends on the `Content-Transfer-Encoding` header, the restrictions have to be disabled:\n    \n    System.setProperty(\"sun.net.http.allowRestrictedHeaders\", \"true\");\n\nSee https://jersey.java.net/nonav/documentation/2.22.1/user-guide.html#d0e4957 for more information on these limitations.\n\n\nContributors\n------------\n\n* [Raffael Stein](https://github.com/rafaroca)\n* [Nico v. Hoyningen-Huene](https://github.com/nicolone)\n\nIf your name is missing, please let us know.\n\n\nLicense\n-------\n\nThis library is licensed under the Apache License, Version 2.0.\n\nSee http://www.apache.org/licenses/LICENSE-2.0.html or the LICENSE file in this repository for the full license text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgini%2Fjersey-smime","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgini%2Fjersey-smime","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgini%2Fjersey-smime/lists"}