{"id":17929466,"url":"https://github.com/marchof/three4j","last_synced_at":"2025-03-24T04:31:03.324Z","repository":{"id":41988395,"uuid":"388196923","full_name":"marchof/three4j","owner":"marchof","description":"Threema Gateway Client for Java","archived":false,"fork":false,"pushed_at":"2024-11-02T19:19:59.000Z","size":110,"stargazers_count":8,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-19T01:45:18.301Z","etag":null,"topics":["cryptography","encryption","end-to-end-encryption","java","messaging","privacy","threema","threema-gateway"],"latest_commit_sha":null,"homepage":"https://github.com/marchof/three4j","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/marchof.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2021-07-21T17:33:14.000Z","updated_at":"2025-03-13T06:39:56.000Z","dependencies_parsed_at":"2024-04-09T19:46:34.914Z","dependency_job_id":"23618c7a-a03d-4b0c-817d-4d6673bacbda","html_url":"https://github.com/marchof/three4j","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marchof%2Fthree4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marchof%2Fthree4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marchof%2Fthree4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marchof%2Fthree4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marchof","download_url":"https://codeload.github.com/marchof/three4j/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245210933,"owners_count":20578316,"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":["cryptography","encryption","end-to-end-encryption","java","messaging","privacy","threema","threema-gateway"],"created_at":"2024-10-28T21:09:21.684Z","updated_at":"2025-03-24T04:31:03.028Z","avatar_url":"https://github.com/marchof.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Three4J - Threema Gateway Client for Java\n=========================================\n\nA Java client library for the [Threema Gateway](https://gateway.threema.ch/)\nwhich supports exchanging end-to-end encrypted messages including images and\narbitrary files. The primary purpose of this implementation is to provide a\nsmall Maven artifact which can be easily integrated in any Java applications.\nThe implementation is based on the [Java 11 HTTP client](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/package-summary.html)\nand [Salty Coffee](https://github.com/NeilMadden/salty-coffee) for NaCl encryption.\n\nThe following resources have been used to implement this API:\n\n* [Threema Message API](https://gateway.threema.ch/en/developer/api)\n* [Threema E2E Message Formats](https://gateway.threema.ch/en/developer/e2e)\n* [Cryptography Whitepaper](https://threema.ch/press-files/2_documentation/cryptography_whitepaper.pdf)\n* [Threema Encryption Validation](https://threema.ch/validation/)\n\nThe API JavaDoc is available [online](https://javadoc.io/doc/com.mountainminds/three4j/).\n\n## Maven Artifacts\n\nThe latest Three4J version can be obtained with the following Maven dependency:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.mountainminds\u003c/groupId\u003e\n    \u003cartifactId\u003ethree4j\u003c/artifactId\u003e\n    \u003cversion\u003e1.4.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nLatest builds from `master` are available in this snapshot repository:\n\u003ca href=\"https://s01.oss.sonatype.org/content/repositories/snapshots/\"\u003ehttps://s01.oss.sonatype.org/content/repositories/snapshots/\u003c/a\u003e\n\n\n## Prerequisites\n\nThree4J requires Java 11 or later.\n\nTo use this library you need a [Threema Gateway](https://gateway.threema.ch/)\naccount with at least one Threema ID and the corresponding key pair. Three4J\ncomes with a main class to generate a new key pair:\n\n```\n$ java com.mountainminds.three4j.KeyGenerator\n\nPLEASE KEEP THE GENERATED KEYS CONFIDENTIAL IF YOU USE THEM WITH A THREEMA ID\nIF YOU LOOSE THE KEY OF A THREEMA ID IT CANNOT BE USED ANY MORE FOR MESSAGING\n\n public key: e25f5e489c458a9eb9d0c07ae44fba34a91b4bd20093e854400998abxxxxxxxx\nprivate key: 93f9873676db87ed2e3ec603645a360c529eb998b35afec17d7cd066xxxxxxxx\n```\n\nPlease consult [Threema's documentation](https://gateway.threema.ch/en/developer/api)\nhow to create a gateway Threema ID.\n\n\n## API Usage Guide\n\n### Setup\n\nTo use the gateway API client you need a gateway Threema ID and the\ncorresponding secret which was issued by the gateway admin interface:\n\n```java\nThreemaId from = ThreemaId.of(\"*YOURGWY\"); // Insert your ID here\nString secret = // e.g. \"JSH5y9DfvOROm2Iw\", retrieve this from a secure location\n```\n\nAll requests are send through a `Gateway` instance:\n\n```java\nGateway gw = new Gateway(from, secret);\n```\n\nIf you want to send end-to-end encrypted messages (which is recommended)\nyou need your private 32 byte Threema key. The hexadecimal string\nrepresentation has 64 characters. Make sure you store this key securely\nand do not make it available to others:\n\n```java\nString myPrivateKeyStr = // retrieve this from a secure location\nPrivateKey myPrivateKey = KeyEncoder.decodePrivateKey(myPrivateKeyStr);\n```\n\n### Lookups\n\nSending a Threema message requires you to know the eight character\nlong Threema ID of the receiver. Users may choose to register their\ntelephone number or email address with their account which can then\nbe queried to lookup their Threema ID. Note that we do not disclose\nthe actual data but only send hash values:\n\n```java\nThreemaId receiverId = gw.getIdByPhoneNumber(Hash.ofPhone(\"+41791234567\"));\nSystem.out.println(receiverId);\n```\n\nOr by Email address:\n\n```java\nreceiverId = gw.getIdByEmailAddress(Hash.ofEmail(\"test@example.com\"));\nSystem.out.println(receiverId);\n```\n\nDepending on the client the receiver might be able to process certain\nmessage types only. You can check the capabilities of a given Threema\nID:\n\n```java\nSystem.out.println(gw.getCapabilities(receiverId));\n```\n\n### Encrypted Text Messages\n\nTo send a encrypted message we need the public key of the receiver\nwhich can be obtained via the gateway API. For better information\nsecurity you should consider obtaining the public key physically\nfrom the receivers device e.g. from the QR code.\n\n```java\nPublicKey receiverPublicKey = gw.getPublicKey(receiverId);\n```\n\nTo ensure end-to-end encryption you create and encrypt the message\nlocally before you send it to the gateway:\n\n```java\nString text = String.format(\"Secret message at %s.\", Instant.now());\n\nPlainMessage msg = new PlainMessage.Text(text);\nEncryptedMessage encrypted = msg.encrypt(myPrivateKey, receiverPublicKey);\nMessageId messageId = gw.sendMessage(receiverId, encrypted);\n\nSystem.out.println(messageId);\n```\n\n### Encrypted Image Messages\n\nSending images requires two steps. First we uploading the image as a\nencrypted blob. Similarly as for the actual message the encryption\nkey for the blob is calculated from our private key and the receivers\npublic key.\n\n```java\nbyte[] image = Files.readAllBytes(Path.of(\"src/test/resources/image.jpg\"));\n\nBlob blob = Blob.newImage(myPrivateKey, receiverPublicKey);\nUploadedBlob uploadedBlob = gw.enrcryptAndUploadBlob(blob, image);\n```\n\nA reference to the uploaded blob needs then to be used in the image message:\n\n```java\nPlainMessage imgMsg = new PlainMessage.Image(uploadedBlob);\nEncryptedMessage encrypted = imgMsg.encrypt(myPrivateKey, receiverPublicKey);\ngw.sendMessage(receiverId, encrypted);\n```\n\nWe can also download and decrypt our image blob again:\n\n```java\nbyte[] downloadedImage = gw.downloadAndDecryptBlob(uploadedBlob);\nFiles.write(Path.of(\"target/download.jpg\"), downloadedImage);\n```\n\n### Encrypted File Messages\n\nWe can encrypt and send arbitrary files. Files are encrypted with a\nrandom key which is then transmitted with the corresponding message.\nAn optional preview image can be added which must be encrypted with\nthe same key than the file:\n\n```java\nbyte[] file = Files.readAllBytes(Path.of(\"src/test/resources/document.pdf\"));\nUploadedBlob uploadedFileBlob = gw.enrcryptAndUploadBlob(Blob.newFile(), file);\n\nbyte[] thumbnail = Files.readAllBytes(Path.of(\"src/test/resources/thumbnail.png\"));\nBlob thumbnailBlob = uploadedFileBlob.thumbnail();\nUploadedBlob uploadedThumbnailBlob = gw.enrcryptAndUploadBlob(thumbnailBlob, thumbnail);\n```\n\nConstruction a file message requires a bit of meta data like the MIME\ntype of the file.\n\n```java\nPlainMessage.File fileMsg = new PlainMessage.File(uploadedFileBlob, \"application/pdf\", RenderingType.DEFAULT);\nfileMsg.setThumbnail(uploadedThumbnailBlob);\nfileMsg.setFileName(\"document.pdf\");\n\nEncryptedMessage encrypted = fileMsg.encrypt(myPrivateKey, receiverPublicKey);\ngw.sendMessage(receiverId, encrypted);\n```\n\n### Simple, Unencrypted Messages\n\nWith a *basic mode* gateway ID you can directly send a plain text\nmessage to a given Threema ID without local encryption. The key pair\nis managed for you on the gateway server. Please rather consider\nusing end-to-end encryption as described above.\n\n```java\ngw.sendSimpleMessage(ThreemaId.of(\"ABCDEFGH\"), \"Not so secret message.\");\n```\n\nAlternatively you can also use a international telephone number or a\nemail address to send a message to if the users has registered them\nwith Threema. Note that the telephone number or the email address is\ndisclosed to the Threema gateway.\n\n```java\ngw.sendSimpleMessageToPhoneNumber(\"41791234567\", \"Not so secret message.\");\ngw.sendSimpleMessageToEmailAddress(\"test@example.com\", \"Not so secret message.\");\n```\n\n### Account Information\n\nThreema charges you for messages and blob uploads via the gateway.\nYou can query the remaining credits via API:\n\n```java\nSystem.out.println(\"Remaining credits: \" + gw.getRemainingCredits());\n```\n\n### Threema QR Code\n\nTo establich trust with your users you can create a QR code with your\nThreema ID and your public key. When the user scans that QR code your\ngateway ID will show \"green\" in their contact list. The `qrcode()`\nmethod creates the text content which need to be converted to a QR\ngraphic with a library of your choice (e.g.\n[zxing](https://github.com/zxing/zxing)).\n\n```java\nPublicKey publicKey = KeyEncoder.getPublicKey(privateKey);\nString qrtext = KeyEncoder.qrcode(threemaid, publicKey);\nSystem.out.println(qrtext);\n```\n\n### Callback Handling\n\nYou can configure your own HTTP server to receive messages from the\nThreema gateway. The corresponding endpoint must be visible from the\npublic internet of course. The payload can be decoded with the\n`GatewayCallback` class:\n\n```java\nbyte[] body = // unprocessed body received from the HTTP server of your choice\n\nGatewayCallback callback = new GatewayCallback(body, secret);\nPublicKey publicKey = gw.getPublicKey(callback.getFrom());\nPlainMessage message = callback.getMessage().decrypt(publicKey, myPrivateKey);\n\nSystem.out.println(message);\n```\n\n\n## Security Disclaimer\n\nThis project has been implemented for personal use only. There was no\nindependent security audit. Please perform your own security audit before using\nthis software to send sensitive content!\n\nAlso make sure you never disclose a private key of a Threema ID. The private\nkey will allow to send messages in your name and decode all content that has\nbeen sent to you.\n\n\n## License\n\nThis code is provided \"as is\" under the [MIT License](LICENSE.md), without warranty of any kind.\n\n\n## Trademarks\n\nThe [Threema Messenger](https://threema.ch/) and the [Messaging Gateway](https://gateway.threema.ch/)\nare products of Threema GmbH, Switzerland. This project has no affiliation to\nThreema GmbH. Please have a look at their [website](https://threema.ch/) and\nconsider using their products for secure end-to-end encrypted communication.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarchof%2Fthree4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarchof%2Fthree4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarchof%2Fthree4j/lists"}