{"id":46551707,"url":"https://github.com/st-user/zerodep-web-push-java","last_synced_at":"2026-03-07T03:32:02.516Z","repository":{"id":39639661,"uuid":"410433183","full_name":"st-user/zerodep-web-push-java","owner":"st-user","description":"A Java Web Push server-side library that can easily be integrated with various third-party libraries and frameworks.","archived":false,"fork":false,"pushed_at":"2026-03-02T03:09:28.000Z","size":880,"stargazers_count":6,"open_issues_count":9,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-02T07:18:50.680Z","etag":null,"topics":["java","webpush"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/st-user.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2021-09-26T02:50:58.000Z","updated_at":"2026-03-02T03:09:31.000Z","dependencies_parsed_at":"2025-12-31T19:03:45.887Z","dependency_job_id":null,"html_url":"https://github.com/st-user/zerodep-web-push-java","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/st-user/zerodep-web-push-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st-user%2Fzerodep-web-push-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st-user%2Fzerodep-web-push-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st-user%2Fzerodep-web-push-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st-user%2Fzerodep-web-push-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/st-user","download_url":"https://codeload.github.com/st-user/zerodep-web-push-java/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st-user%2Fzerodep-web-push-java/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30206570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T03:24:23.086Z","status":"ssl_error","status_checked_at":"2026-03-07T03:23:11.444Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["java","webpush"],"created_at":"2026-03-07T03:32:02.056Z","updated_at":"2026-03-07T03:32:02.497Z","avatar_url":"https://github.com/st-user.png","language":"Java","readme":"# zerodep-web-push-java\n\nA Java [Web Push](https://datatracker.ietf.org/doc/html/rfc8030) server-side library that can easily\nbe integrated with various third-party libraries and frameworks.\n\nThis library\n\n- Provides the functionalities for [VAPID](https://datatracker.ietf.org/doc/html/rfc8292)\n- Provides the functionalities\n  for [Message Encryption for Web Push](https://datatracker.ietf.org/doc/html/rfc8291)\n- Assumes that the [Push API](https://www.w3.org/TR/push-api/) is used\n\n## Versions\n\n| zerodep-web-push-java | java version requirements |\n|-----------------------|---------------------------|\n| v2.x.x                | java 11 or higher         |\n| v1.x.x                | java 8 or higher          |\n\nIt is recommended that you use v2.x.x (the latest version of v2) if you can use java 11 or higher.\nSome features are only available in version 2.\n\nThe documentation specific to v1 is [here](https://github.com/st-user/zerodep-web-push-java/tree/main-v1).\n\n\n## Installation\n\n``` xml\n\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.zerodeplibs\u003c/groupId\u003e\n  \u003cartifactId\u003ezerodep-web-push-java\u003c/artifactId\u003e\n  \u003cversion\u003e2.1.5\u003c/version\u003e\n\u003c/dependency\u003e\n\n```\n\n## How to use\n\nSending push notifications requires slightly complex steps. So it is recommended that you check one of the example projects(Please see [Examples](#examples)).\n\nThe following is a typical flow to send push notifications with this library.\n\n1. Generate a key pair for VAPID with an arbitrary way(e.g. openssl commands).\n\n    Example:\n    ``` bash\n    openssl ecparam -genkey -name prime256v1 -noout -out sourceKey.pem\n    openssl pkcs8 -in sourceKey.pem -topk8 -nocrypt -out vapidPrivateKey.pem\n    openssl ec -in sourceKey.pem -pubout -conv_form uncompressed -out vapidPublicKey.pem\n    ```\n\n2. Instantiate `VAPIDKeyPair` with the key pair generated in '1.'.\n\n    Example:\n    ``` java\n    VAPIDKeyPair vapidKeyPair = VAPIDKeyPairs.of(\n        PrivateKeySources.ofPEMFile(new File(pathToYourPrivateKeyFile).toPath()),\n        PublicKeySources.ofPEMFile(new File(pathToYourPublicKeyFile).toPath()\n    );\n    ```\n\n3. Send the public key for VAPID to the browser.\n\n    Typically, this is achieved by exposing an endpoint to get the public key like `GET /getPublicKey`. Javascript on the browser fetches the public key through this endpoint.\n\n    Example:\n    ``` java\n    @GetMapping(\"/getPublicKey\")\n    public byte[] getPublicKey() {\n        return vapidKeyPair.extractPublicKeyInUncompressedForm();\n    }\n    ```\n   (javascript on browser)\n    ``` javascript\n    const serverPublicKey = await fetch('/getPublicKey')\n                                    .then(response =\u003e response.arrayBuffer());\n\n    const subscription = await registration.pushManager.subscribe({\n        userVisibleOnly: true,\n        applicationServerKey: serverPublicKey\n    });\n    ```\n\n4. Obtain a push subscription from the browser.\n\n    Typically, this is achieved by exposing an endpoint for the browser to post the push subscription like `POST /subscribe`.\n\n    Example:\n    ``` java\n    @PostMapping(\"/subscribe\")\n    public void subscribe(@RequestBody PushSubscription subscription) {\n       this.saveSubscriptionToStorage(subscription);\n    }\n    ```\n   (javascript on browser)\n    ``` javascript\n    await fetch('/subscribe', {\n        method: 'POST',\n        body: JSON.stringify(subscription),\n        headers: {\n            'content-type': 'application/json'\n        }\n    }).then(res =\u003e {\n       .....\n    });\n    ```\n   \n\n5. Send a push notification to the push service by using RequestPreparer (e.g. `StandardHttpClientRequestPreparer`) with the `VAPIDKeyPair` and the push subscription.\n\n    ``` java\n    HttpRequest request = StandardHttpClientRequestPreparer.getBuilder()\n        .pushSubscription(subscription)\n        .vapidJWTExpiresAfter(15, TimeUnit.MINUTES)\n        .vapidJWTSubject(\"mailto:example@example.com\")\n        .pushMessage(message)\n        .ttl(1, TimeUnit.HOURS)\n        .urgencyLow()\n        .topic(\"MyTopic\")\n        .build(vapidKeyPair)\n        .toRequest();\n   \n    HttpResponse\u003cString\u003e httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString());\n    ```\n\n\n## Examples\n\n### Spring Boot (MVC)\n\nSource code and usage: [examples/basic](./examples/basic)\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cb\u003eController for VAPID and Message Encryption\u003c/b\u003e\u003c/summary\u003e\n    \n``` java\n    \n@Component\npublic class MyComponents {\n\n    /**\n     * In this example, we read a key pair for VAPID\n     * from a PEM formatted file on the file system.\n     * \u003cp\u003e\n     * You can extract key pairs from various sources:\n     * '.der' file(binary content), an octet sequence stored in a database and so on.\n     * For more information, please see the javadoc of PrivateKeySources and PublicKeySources.\n     */\n    @Bean\n    public VAPIDKeyPair vaidKeyPair(\n        @Value(\"${private.key.file.path}\") String privateKeyFilePath,\n        @Value(\"${public.key.file.path}\") String publicKeyFilePath) throws IOException {\n\n        return VAPIDKeyPairs.of(\n            PrivateKeySources.ofPEMFile(new File(privateKeyFilePath).toPath()),\n            PublicKeySources.ofPEMFile(new File(publicKeyFilePath).toPath())\n        );\n    }\n\n}\n\n    \n@SpringBootApplication\n@RestController\npublic class BasicExample {\n\n    /**\n     * @see MyComponents\n     */\n    @Autowired\n    private VAPIDKeyPair vapidKeyPair;\n\n    /**\n     * # Step 1.\n     * Sends the public key to user agents.\n     * \u003cp\u003e\n     * The user agents create a push subscription with this public key.\n     */\n    @GetMapping(\"/getPublicKey\")\n    public byte[] getPublicKey() {\n        return vapidKeyPair.extractPublicKeyInUncompressedForm();\n    }\n\n    /**\n     * # Step 2.\n     * Obtains push subscriptions from user agents.\n     * \u003cp\u003e\n     * The application server(this application) requests the delivery of push messages with these subscriptions.\n     */\n    @PostMapping(\"/subscribe\")\n    public void subscribe(@RequestBody PushSubscription subscription) {\n        this.saveSubscriptionToStorage(subscription);\n    }\n\n    /**\n     * # Step 3.\n     * Requests the delivery of push messages.\n     * \u003cp\u003e\n     * In this example, for simplicity and testability, we use an HTTP endpoint for this purpose.\n     * However, in real applications, this feature doesn't have to be provided as an HTTP endpoint.\n     */\n    @PostMapping(\"/sendMessage\")\n    public ResponseEntity\u003cString\u003e sendMessage(@RequestBody MyMessage myMessage)\n        throws IOException, InterruptedException {\n\n        String message = myMessage.getMessage();\n\n        HttpClient httpClient = HttpClient.newBuilder().build();\n        for (PushSubscription subscription : getSubscriptionsFromStorage()) {\n\n            HttpRequest request = StandardHttpClientRequestPreparer.getBuilder()\n                .pushSubscription(subscription)\n                .vapidJWTExpiresAfter(15, TimeUnit.MINUTES)\n                .vapidJWTSubject(\"mailto:example@example.com\")\n                .pushMessage(message)\n                .ttl(1, TimeUnit.HOURS)\n                .urgencyLow()\n                .topic(\"MyTopic\")\n                .build(vapidKeyPair)\n                .toRequest();\n\n            // In this example, we send push messages in simple text format.\n            // You can also send them in JSON format as follows:\n            //\n            // ObjectMapper objectMapper = (Create a new one or get from the DI container.)\n            // ....\n            // .pushMessage(objectMapper.writeValueAsBytes(objectForJson))\n            // ....\n\n            HttpResponse\u003cString\u003e httpResponse =\n                httpClient.send(request, HttpResponse.BodyHandlers.ofString());\n            logger.info(String.format(\"[Http Client] status code: %d\", httpResponse.statusCode()));\n            // 201 Created : Success!\n            // 410 Gone : The subscription is no longer valid.\n            // etc...\n            // for more information, see the useful link below:\n            // [Response from push service - The Web Push Protocol ](https://developers.google.com/web/fundamentals/push-notifications/web-push-protocol)\n        }\n\n        return ResponseEntity.ok()\n            .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)\n            .body(\"The message has been processed.\");\n    }\n    \n    ... Omitted for simplicity.\n    \n}\n    \n```\n    \n\u003c/details\u003e\n\n### Spring Boot (WebFlux)\n\nSource code and usage: [examples/webflux](./examples/webflux)\n\n### Vert.x\n\nSource code and usage: [examples/vertx](./examples/vertx) \n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cb\u003eStandalone application for VAPID and Message Encryption\u003c/b\u003e\u003c/summary\u003e\n\n``` java\n\npublic class Example {\n\n    /**\n     * In this example, we read a key pair for VAPID\n     * from a PEM formatted file on the file system.\n     * \u003cp\u003e\n     * You can extract key pairs from various sources:\n     * '.der' file(binary content), an octet sequence stored in a database and so on.\n     * For more information, please see the javadoc of PrivateKeySources and PublicKeySources.\n     */\n    private static VAPIDKeyPair createVAPIDKeyPair(Vertx vertx) throws IOException {\n        return VAPIDKeyPairs.of(\n            PrivateKeySources.ofPEMFile(new File(\"./.keys/my-private_pkcs8.pem\").toPath()),\n            PublicKeySources.ofPEMFile(new File(\"./.keys/my-pub.pem\").toPath()),\n            new VertxVAPIDJWTGeneratorFactory(() -\u003e vertx));\n    }\n\n    public static void main(String[] args) throws IOException {\n\n        Vertx vertx = Vertx.vertx();\n        WebClient client = WebClient.create(vertx);\n        Router router = Router.router(vertx);\n        router.route().handler(BodyHandler.create());\n\n        VAPIDKeyPair vapidKeyPair = createVAPIDKeyPair(vertx);\n        MockSubscriptionStorage mockStorage = new MockSubscriptionStorage();\n\n        /*\n         * # Step 1.\n         * Sends the public key to user agents.\n         *\n         * The user agents create a push subscription with this public key.\n         */\n        router\n            .get(\"/getPublicKey\")\n            .handler(ctx -\u003e\n                ctx.response()\n                    .putHeader(\"Content-Type\", \"application/octet-stream\")\n                    .end(Buffer.buffer(vapidKeyPair.extractPublicKeyInUncompressedForm()))\n            );\n\n        /*\n         * # Step 2.\n         * Obtains push subscriptions from user agents.\n         *\n         * The application server(this application) requests the delivery of push messages with these subscriptions.\n         */\n        router\n            .post(\"/subscribe\")\n            .handler(ctx -\u003e {\n\n                PushSubscription subscription =\n                    ctx.getBodyAsJson().mapTo(PushSubscription.class);\n                mockStorage.saveSubscriptionToStorage(subscription);\n\n                ctx.response().end();\n            });\n\n        /*\n         * # Step 3.\n         * Requests the delivery of push messages.\n         *\n         * In this example, for simplicity and testability, we use an HTTP endpoint for this purpose.\n         * However, in real applications, this feature doesn't have to be provided as an HTTP endpoint.\n         */\n        router\n            .post(\"/sendMessage\")\n            .handler(ctx -\u003e {\n\n                String message = ctx.getBodyAsJson().getString(\"message\");\n                vertx.getOrCreateContext().put(\"messageToSend\", new SampleMessageData(message));\n\n                ExamplePushMessageDeliveryRequestProcessor processor =\n                    new ExamplePushMessageDeliveryRequestProcessor(\n                        vertx,\n                        client,\n                        vapidKeyPair,\n                        mockStorage.getSubscriptionsFromStorage()\n                    );\n                processor.start();\n\n                ctx.response()\n                    .putHeader(\"Content-Type\", \"text/plain\")\n                    .end(\"Started sending notifications.\");\n            });\n\n        router.route(\"/*\").handler(StaticHandler.create());\n\n        vertx.createHttpServer().requestHandler(router).listen(8080, res -\u003e {\n            System.out.println(\"Vert.x HTTP server started.\");\n        });\n    }\n\n    /**\n     * Sends HTTP requests to push services to request the delivery of push messages.\n     * \u003cp\u003e\n     * This class utilizes:\n     * \u003cul\u003e\n     * \u003cli\u003e{@link Vertx#executeBlocking(Handler, Handler)} for the JWT creation and the message encryption.\u003c/li\u003e\n     * \u003cli\u003e{@link WebClient} for sending HTTP request asynchronously.\u003c/li\u003e\n     * \u003c/ul\u003e\n     */\n    static class ExamplePushMessageDeliveryRequestProcessor {\n\n        private final Vertx vertx;\n        private final WebClient client;\n        private final VAPIDKeyPair vapidKeyPair;\n        private final List\u003cPushSubscription\u003e targetSubscriptions;\n\n        private final int requestIntervalMillis;\n        private final int connectionTimeoutMillis;\n\n        ExamplePushMessageDeliveryRequestProcessor(\n            Vertx vertx,\n            WebClient client,\n            VAPIDKeyPair vapidKeyPair,\n            Collection\u003cPushSubscription\u003e targetSubscriptions) {\n\n            this.vertx = vertx;\n            this.client = client;\n            this.vapidKeyPair = vapidKeyPair;\n            this.targetSubscriptions = targetSubscriptions.stream().collect(Collectors.toList());\n            this.requestIntervalMillis = 100;\n            this.connectionTimeoutMillis = 10_000;\n        }\n\n        void start() {\n            startInternal(0);\n        }\n\n        private void startInternal(int currentIndex) {\n\n            PushSubscription subscription = targetSubscriptions.get(currentIndex);\n            SampleMessageData messageData = vertx.getOrCreateContext().get(\"messageToSend\");\n\n            vertx.executeBlocking(promise -\u003e {\n\n                // In some circumstances, the JWT creation and the message encryption\n                // may be considered \"blocking\" operations.\n                //\n                // On the author's environment, the JWT creation takes about 0.7ms\n                // and the message encryption takes about 1.7ms.\n                //\n                // reference: https://vertx.io/docs/vertx-core/java/#golden_rule\n\n                VertxWebClientRequestPreparer requestPreparer =\n                    VertxWebClientRequestPreparer.getBuilder()\n                        .pushSubscription(subscription)\n                        .vapidJWTExpiresAfter(15, TimeUnit.MINUTES)\n                        .vapidJWTSubject(\"mailto:example@example.com\")\n                        .pushMessage(messageData.getMessage())\n                        .ttl(1, TimeUnit.HOURS)\n                        .urgencyNormal()\n                        .topic(\"MyTopic\")\n                        .build(vapidKeyPair);\n\n                promise.complete(requestPreparer);\n\n            }, res -\u003e {\n\n                VertxWebClientRequestPreparer requestPreparer =\n                    (VertxWebClientRequestPreparer) res.result();\n                requestPreparer.sendBuffer(\n                    client,\n                    req -\u003e req.timeout(connectionTimeoutMillis),\n                    httpResponseAsyncResult -\u003e {\n\n                        HttpResponse\u003cBuffer\u003e result = httpResponseAsyncResult.result();\n                        System.out.println(\n                            String.format(\"status code: %d\", result.statusCode()));\n                        // 201 Created : Success!\n                        // 410 Gone : The subscription is no longer valid.\n                        // etc...\n                        // for more information, see the useful link below:\n                        // [Response from push service - The Web Push Protocol ](https://developers.google.com/web/fundamentals/push-notifications/web-push-protocol)\n\n                    }\n                );\n\n            });\n\n            if (currentIndex == targetSubscriptions.size() - 1) {\n                return;\n            }\n\n            // In order to avoid wasting bandwidth,\n            // we send HTTP requests at some intervals.\n            vertx.setTimer(requestIntervalMillis, id -\u003e startInternal(currentIndex + 1));\n        }\n    }\n    \n    ... Omitted for simplicity.\n    \n}\n\n```\n\n\u003c/details\u003e\n\n## Motivation\n\n'zerodep-web-push-java' assumes that suitable implementations(libraries) of the following\nfunctionalities vary depending on applications.\n\n- Generating and signing JSON Web Token(JWT) used for VAPID\n- Sending HTTP requests for the delivery of push messages\n- Cryptographic operations\n\nFor example, an application may need to send HTTP requests **synchronously**\nwith [Apache HTTPClient](https://hc.apache.org/httpcomponents-client-5.1.x/) but another application\nmay need to do this **asynchronously** with [Vert.x](https://vertx.io/docs/vertx-web-client/java/).\n\nIn order to allow you to choose the way suitable for your application, this library doesn't force\nyour application to have dependencies on specifics libraries. Instead, this library\n\n- Provides the functionality of JWT for VAPID\n  with [sub-modules](./ext-jwt)\n- Also, provides the functionality of JWT for VAPID out of the box(without any third-party library)\n- Provides optional components helping applications use various third-party HTTP Client libraries\n- Also, provides a component helping applications use [JDK's HTTP Client module](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html).\n- Utilizes\n  [the Java Cryptography Architecture (JCA)](https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html)\n  for cryptographic operations\n\nEach of the sub-modules utilizes a specific JWT library. Each of the optional components supports a\nspecific HTTP Client library. you can choose suitable modules/components for your requirements. JCA\nenables this library to be independent of specific implementations(providers) for security\nfunctionality.\n\n## Various sub-modules and helper components\n\nThe following functionalities can be provided from outside this library.\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cb\u003eJWT\u003c/b\u003e\u003c/summary\u003e\n\nJWT libraries are used to generate JSON Web Token (JWT)\nfor [VAPID](https://datatracker.ietf.org/doc/html/rfc8292).\n\nSub-modules for this functionality are available\nfrom [ext-jwt](./ext-jwt).\n\nThese sub-modules are optional.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cb\u003eHTTP Client\u003c/b\u003e\u003c/summary\u003e\n\nApplication servers need to send HTTP requests to push services in order to request the delivery of\npush messages. Helper components for this functionality are available from\nthe `com.zerodeplibs.webpush.httpclient` package. One of them\nutilizes [JDK's HTTP Client module](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html)\n.\nThe others utilize third-party HTTP Client libraries. Supported third-party libraries are listed\nbelow.\n\n- [OkHttp](https://square.github.io/okhttp/)\n\n  Version 4.9.0 or higher. The latest version is recommended.\n\n- [Apache HTTPClient](https://hc.apache.org/httpcomponents-client-5.1.x/)\n\n  Version 5.1 or higher. The latest version is recommended.\n\n- [Eclipse Jetty Client Libraries](https://www.eclipse.org/jetty/documentation/jetty-11/programming-guide/index.html#pg-client)\n\n    - Jetty 9: 9.4.33.v20201020 or higher.\n    - Jetty 10: 10.0.0 or higher.\n    - Jetty 11: 11.0.0 or higher.\n\n  The latest versions are recommended.\n\n- [Vert.x Web Client](https://vertx.io/docs/vertx-web-client/java/)\n\n    - Vert.x 3: 3.9.2 or higher.\n    - Vert.x 4: 4.0.0 or higher.\n\n  The latest versions are recommended.\n\n- **Others**\n  \n  'zerodep-web-push-java' doesn't directly provide optional components for the libraries other than the above. However, 'zerodep-web-push-java' can be easily integrated with the other HTTP Client libraries and frameworks.\n  For example, you can also utilize the following libraries.\n\n  - [Spring WebFlux (WebClient)](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-client)\n  - [Reactor Netty HTTP Client](https://projectreactor.io/docs/netty/release/reference/index.html#http-client)\n\n  Please see [examples/webflux](./examples/webflux) for more information.\n\n\n\u003c/details\u003e\n\n## MISC\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cb\u003eNull safety\u003c/b\u003e\u003c/summary\u003e\n\nThe public methods and constructors of this library do not accept `null`s and do not return `null`s.\nThey throw an `Exception` if a null reference is passed. Some methods\nreturn `java.util.Optional.empty()` if they need to indicate that the value does not exist.\n\nThe exceptions are:\n\n- `com.zerodeplibs.webpush.PushSubscription.java`. This is the server-side representation\n  of [push subscription](https://www.w3.org/TR/push-api/#push-subscription).\n- The methods of `Exception`. For example, their `getCause()` can return null.\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cb\u003eWorking with Java Cryptography Architecture(JCA)\u003c/b\u003e\u003c/summary\u003e\n\nThis library\nuses [the Java Cryptography Architecture (JCA)](https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html)\nAPI for cryptographic operations. The algorithms used by this library are listed below.\n\n``` java\njava.security.SecureRandom\njava.security.KeyFactory.getInstance(\"EC\") \njava.security.KeyPairGenerator.getInstance(\"EC\") // curve: secp256r1\njava.security.Signature.getInstance(\"SHA256withECDSA\")\njavax.crypto.KeyAgreement.getInstance(\"ECDH\")\njavax.crypto.Mac.getInstance(\"HmacSHA256\") \njavax.crypto.Cipher.getInstance(\"AES/GCM/NoPadding\")\n```\n\nBy default, the providers shipped with the JDK will be used(e.g. `SunEC` and `SunJCE`).\n\nOf course, any provider that supports these algorithms is available(\ne.g. [Bouncy Castle](https://bouncycastle.org/)). This is because 'zerodep-web-push-java' has no\ndependencies on any specific provider.\n\n\u003c/details\u003e\n\n## License\n\nMIT\n\n## Contribution\n\nThis project follows a [git flow](https://nvie.com/posts/a-successful-git-branching-model/) -style\nmodel.\n\nPlease open pull requests against the `dev` branch.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fst-user%2Fzerodep-web-push-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fst-user%2Fzerodep-web-push-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fst-user%2Fzerodep-web-push-java/lists"}