{"id":16156391,"url":"https://github.com/flowdalic/java-pinning","last_synced_at":"2025-11-10T00:03:22.064Z","repository":{"id":23287186,"uuid":"26646135","full_name":"Flowdalic/java-pinning","owner":"Flowdalic","description":"TLS pinning for Java","archived":false,"fork":false,"pushed_at":"2024-11-18T08:05:38.000Z","size":142,"stargazers_count":39,"open_issues_count":3,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-16T23:34:20.063Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/Flowdalic.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}},"created_at":"2014-11-14T16:04:12.000Z","updated_at":"2024-11-18T08:05:42.000Z","dependencies_parsed_at":"2022-08-05T22:00:16.346Z","dependency_job_id":null,"html_url":"https://github.com/Flowdalic/java-pinning","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowdalic%2Fjava-pinning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowdalic%2Fjava-pinning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowdalic%2Fjava-pinning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowdalic%2Fjava-pinning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Flowdalic","download_url":"https://codeload.github.com/Flowdalic/java-pinning/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244301224,"owners_count":20430905,"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":[],"created_at":"2024-10-10T01:44:48.961Z","updated_at":"2025-11-10T00:03:22.026Z","avatar_url":"https://github.com/Flowdalic.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Java Pinning\n============\n\nJava Pinning provides support for pinning TLS (and SSL) certificates without any CA validation required.\nThe library runs on Java and Android and is available from Maven Central. It is licensed under the Apache License, Version 2.0.\nIf Java Pinning **pins the public key** of a certificate, or the hash of such, and produces a SSLContext which will only accept connections to a host in possession of the corresponding private key.\nThere is no additional validation using the system's trust store, i.e. Java Pinning disables PKI (CA validation).\nThis means that as soon as the private key is compromised, an attacker will be able to impersonate the host.\n\nYou should only use Java Pinning if you are in control of both ends of the TLS connection, so that you can replace the Pin in case the private key has been compromised.\nTo be absolutely clear: **If you need to change the server certificate, you need to change also the PIN in the client**.\nUsually you want to add the new PIN first, before changing the server certificate.\nIf you don't add the new PIN, your clients wont be able to connect to your server!\nPlease inform yourself about the available alternatives to Java Pinning to determine if your use case is a match for Java Pinning.\nSee also the \"Alternatives\" section in this README.\n\nHow to use\n----------\n\n### XMPP Users\n\nIf your XMPP service does not provide you the server certificates SHA256 hash or the full certificate over a secure channel, then you could obtain the information for example via `xmpp.net`:\n\n1. Go to [xmpp.net](https://xmpp.net)\n2. Select \"Test a server\", enter your service name and make sure \"c2s\" is selected\n3. Press \"Check!\"\n4. Wait a bit until the information in the \"Certificates\" section appears\n5. The first certificate (\"#0\") is the one of your service. In the \"Details\" section select SHA-256\n6. Copy the SHA-256 hash, e.g. `83:F9:17:1E:06:A3:13:11:88:89:F7:D7:93:02:BD:1B:7A:20:42:EE:0C:FD:02:9A:BF:8D:D0:6F:FA:6C:D9:D3`\n7. Java Pinning versions \u003c 1.0.1 require the colons to be removed and the letters to be lowercase. This transformation could be done with the following bash script\n\n```bash\n$ pin=83:F9:17:1E:06:A3:13:11:88:89:F7:D7:93:02:BD:1B:7A:20:42:EE:0C:FD:02:9A:BF:8D:D0:6F:FA:6C:D9:D3\n$ echo $pin | tr '[:upper:]' '[:lower:]' | tr -d :\n```\n\n8. Create the Java Pinning Pin String by prefixing `CERTSHA256` to the Pin. Thus our example SHA256 value becomes `CERTSHA256:83:F9:17:1E:06:A3:13:11:88:89:F7:D7:93:02:BD:1B:7A:20:42:EE:0C:FD:02:9A:BF:8D:D0:6F:FA:6C:D9:D3`\n\n### HTTPS (and other services using TLS right from the start)\n\n```bash\n$ ./tools/pin.py example.org 443\nCalculating PIN for certificate: CN=example.org\nCertificate Fingerprint (SHA256): 4CBF7A80EC338E34DC4DA50136AFF0B6C1D91F1DD87BBF56FB0EBA3FC7451835\nPin Value: SHA256:e3b1812d945da1a2a2c5fa28029d2fe34c7c4142fb098f5cfedff1ff20e98781\nPin Value: PLAIN:30820222300d06092a864886f70d01010105000382020f003082020a0282020100b2617fdff43d5c469f067e879b6a0f5a721f6b17f2231942e3de417f16ab5ec4a50bd3cfbeb38c1dc942f333fd8056c28f07373178faa48700770be6c1ece59c3286e7c1992b23c7e1a328adddb58d06fde0ef87d95357d916fdce995921a49a54dd992ff8a87d0534d9b5988914a1ecf348815f125e4c156c7dcbe966717d3a7dd5f33999686aecc8ddbfc4f24ee7155cf09fe99229f47e7939b560e1bec8815f751fc7e864322d0bc56bfe0876cbfd642a554237f9ccca076f8b8a97d0cccb49a05894bed6bcd405e3b0325c4a5950ef19b4399ad504d3a6e5c1c77d9cb43c74016bebecbc62d90a6cf5c5388ad7e38f18cd19b26a222d8909e3d8a306c9ae81f3582ae775b8cd5766e001713209d807f033ab3e2041e030c85d08982bb2fa50205caad78984f682873dd4f6f8e2c044cfe5a8c804c3c7300ba75b692f5f4b8c0ebb10cf375424fe97e19962bf4fddf6a9c704ba50cd6870733f78f33a39b00098ce10ebafb54b2946e4739ad20d17c6e6c6985b07c55bde518b328bce9e9745b7c8c659aca5057d705f9ce4cfcfc8141e9ad3688516914462e278458a729455d79cb5f9e4f1d6bf11d51cda4b5a08799c7b9826692f00f3c07891fe8565d654c0a49e9be3d91285a11aa01fc608b4cd606dac7ad427a4641c03c64bc8c9fffe252b6293d606e7c2224e47da98c357f44a720c42ccb2cb7663bd2fe86bfc870203010001\n```\n\n\n```java\nX509TrustManager tm = Java7Pinning\n  .trustManagerForPin(\"SHA256:e3b1812d945da1a2a2c5fa28029d2fe34c7c4142fb098f5cfedff1ff20e98781\");\n```\n\nNow you can setup this context.\n\nExamples\n--------\n\n# [Smack](http://www.igniterealtime.org/projects/smack/)\n\n\n```java\nX509TrustManager tm = Java7Pinning\n  .trustManagerForPin(\"SHA256:e3b1812d945da1a2a2c5fa28029d2fe34c7c4142fb098f5cfedff1ff20e98781\");\nXMPPTCPConnectionConfiguration conf = XMPPTCPConnectionConfiguration.builder()\n  .setUsernameAndPassword(\"user\", \"pass\")\n  .setService(\"example.org\")\n  .setCustomX509TrustManager(tm)\n  .build()\n```\n\nHow to add this as dependency\n-----------------------------\n\n### Gradle\n\n```groovy\ncompile('eu.geekplace.javapinning:java-pinning-core:1.3.0')\n```\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003eeu.geekplace.javapinning\u003c/groupId\u003e\n\t\u003cartifactId\u003ejava-pinning-core\u003c/artifactId\u003e\n\t\u003cversion\u003e1.3.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nDifference between Public Key Pins and Certificate Pins\n-------------------------------------------------------\n\nBoth provide the same security guarantee.\nIf the private key is compromised, both can no longer provide a security guarantee.\nUsing Public Key pinning provides (theoretically) the advantage that the certificate could be replaced with a new one using the same private/public key pair, thus requiring no changes to the used Pins.\n\nAlternatives\n============\n\nJava (and Android)\n------------------\n\n### Pure Certificate Pinning\n\nThis technique creates a custom SSLContext that will only accept certificates found or signed by certificates in a key store file.\n\n```java\nFile keyStoreFile = new File(\"./myKeyStore\");\nKeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());\nks.load(new FileInputStream(keyStoreFile), \"keyStorePassword\".toCharArray());\nTrustManagerFactory tmf = TrustManagerFactory.getInstance(\"X509\");\ntmf.init(ks);\nSSLContext sc = SSLContext.getInstance(\"TLS\");\nsc.init(null, tmf.getTrustManagers(), new java.security.SecureRandom());\n```\n\nYou can read more about it at https://op-co.de/blog/posts/java_sslsocket_mitm/#index10h3\n\nAndroid\n-------\n\n### [Memorizing Trust Manager](https://github.com/ge0rg/MemorizingTrustManager)\n\nMemorizing Trust Manager (MTM) excels in user scenarios because of its GUI confirmation dialog.\nMTM does pin the certificate and does also not perform additional validate by the system trust store.\nIt is only available on Android (at the moment).\n\n### [Android Pinning](https://github.com/moxie0/AndroidPinning)\n\nAndroid Pinning (AP) does additional validate the pinned certificate by using the system's trust store.\nIt provides probably the best level of security, as it additionally strengthens PKI with pinning.\nAs the name suggests, Android Pinning is only available for Android.\nThe fact that the last commit date is June 2013 makes it questionable if the project is still actively maintained.\n\n\nBuild Instructions\n==================\n\nBuild with\n\n```bash\ngradle build\n```\n\nRun tests with\n\n```bash\ngradle check\n```\n\nChangelog\n---------\n\n### 1.3.0\n\n- Require Java 11\n\n### 1.2.0\n\n- Fix dependency declarations\n\n### 1.1.0\n\n- Added support for the Java 7 `X509ExtendedTrustManager` if your project uses Java 7 please use `Java7Pinning` instead of `JavaPinning`.\n- Two new factory methods `JavaPinning.trustManagerForPins(String...)` and `JavaPinning.forPins(String...)`.\n- Deprecated `JavaPinning.trustManagerforpins()` in favor of the correctly named `JavaPinning.trustManagerForpins()`.\n- Two new factory methods `CertPlainPin.fromCertificate` and `PlainPin.fromPublicKey` these methods can be used to directly create pins from X509 certificates or X509 public keys.\n- Two new getter methods `CertPlainPin.getX509Certificate()` and `PlainPin.getPublicKey()`.\n- Two new factory methods in `JavaPinning`\n- The `PinningTrustManager` now throws a specialized exception when a certificate is not pinned `CertificateNotPinnedException` which is a sub-type of `CertificateException`, this allows you to differentiate pinning exceptions from other certificate related exceptions.\n- New class `HexUtilities` which contains methods to decode from HEX to bytes and encode bytes to HEX\n- The `JavaPinningUtil` class has been deprecated in favor of `HexUtilities`, beaware of the fact that the methods in `HexUtilities` behave slightly better, but different).\n\n### 1.0.1\n\nThe Pin format requirements have been relaxed. The Pin string may now contain\n\n- Colons (':')\n- Uppercase characters\n- Spaces\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflowdalic%2Fjava-pinning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflowdalic%2Fjava-pinning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflowdalic%2Fjava-pinning/lists"}