{"id":51606175,"url":"https://github.com/sureshg/certkit","last_synced_at":"2026-07-12T02:30:30.306Z","repository":{"id":338760579,"uuid":"1152977061","full_name":"sureshg/certkit","owner":"sureshg","description":"🧬 Kotlin/JVM toolkit for X.509 certs, PEM/DER encoding, CSR, CRL and TLS scanning","archived":false,"fork":false,"pushed_at":"2026-07-04T06:31:29.000Z","size":1331,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-04T08:22:27.696Z","etag":null,"topics":["amper","certificate","java","jdk","jvm","kotlin","kotlin-jvm","kotlin-toolchain","pem","security","tls","x509"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sureshg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":null,"dco":null,"cla":null}},"created_at":"2026-02-08T18:05:26.000Z","updated_at":"2026-07-04T06:29:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sureshg/certkit","commit_stats":null,"previous_names":["sureshg/certkit"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/sureshg/certkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sureshg%2Fcertkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sureshg%2Fcertkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sureshg%2Fcertkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sureshg%2Fcertkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sureshg","download_url":"https://codeload.github.com/sureshg/certkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sureshg%2Fcertkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35380480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"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":["amper","certificate","java","jdk","jvm","kotlin","kotlin-jvm","kotlin-toolchain","pem","security","tls","x509"],"created_at":"2026-07-12T02:30:29.824Z","updated_at":"2026-07-12T02:30:30.275Z","avatar_url":"https://github.com/sureshg.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/banner.png\" alt=\"certkit\"/\u003e\n\u003c/p\u003e\n\n[![GitHub Workflow Status][gha_badge]][gha_url]\n[![Maven Central Version][maven_img]][maven_url]\n[![Kotlin release][kt_img]][kt_url]\n[![OpenJDK Version][java_img]][java_url]\n[![Test Report][test_img]][test_url]\n\nLightweight X.509 certificate toolkit for Kotlin/JVM. Build self-signed certs, CSRs, CRLs, and work with PEM/DER\nencoding, all using JDK standard libraries. **No BouncyCastle, no Guava.**\n\n## Features\n\n- **Self-signed certificates** — X.509v3 with SAN, Basic Constraints, key identifiers (EC keys)\n- **CSR creation** — PKCS#10 Certificate Signing Requests with SAN support\n- **CRL support** — parse, build, and check certificate revocation lists\n- **PEM read/write** — load and encode certificates, private keys, public keys\n- **DER DSL** — type-safe Kotlin DSL for building ASN.1 DER structures\n- **Private key formats** — PKCS#8, PKCS#8 encrypted, PKCS#1 (RSA, DSA, EC)\n- **TLS scanning** — connect to any host and capture the certificate chain\n\n## 🚀 Quick Start\n\n\u003e **Requires JDK 21+**\n\n```kotlin\ndependencies {\n    implementation(\"dev.suresh.certkit:certkit:0.4.0\")\n}\n```\n\n### Self-Signed Certificate\n\n```kotlin\nval keyPair = newEcKeyPair()\nval today = Clock.System.todayIn(TimeZone.UTC)\n\nval cert = Cert.buildSelfSigned(\n    keyPair = keyPair,\n    serialNumber = 1,\n    issuer = X500Principal(\"CN=My CA,O=TestOrg\"),\n    subject = X500Principal(\"CN=My CA,O=TestOrg\"),\n    notBefore = today,\n    notAfter = today + DatePeriod(days = 30),\n    sans = [San.Dns(\"localhost\"), San.Dns(\"*.local\"), San.Ip(\"127.0.0.1\")],\n)\n\nprintln(cert.pem)\n```\n\nAn `Instant` overload is also available for precise control over validity times.\n\n### Certificate Extensions\n\n```kotlin\ncert.commonName          // \"My CA\"\ncert.subjectAltNames     // [\"localhost\", \"*.local\", \"127.0.0.1\"]\ncert.expiryDateUtc       // 2026-04-07T23:59:59\ncert.isExpired           // false\ncert.expiresIn           // 30d 0h ...\ncert.isCA                // true\ncert.selfSigned          // true\ncert.signedBy(caCert)    // true\n```\n\n### PEM\n\n```kotlin\n// Load\nval privateKey = Pem.loadPrivateKey(Path(\"server.key\"), keyPassword = \"secret\")\nval publicKey = Pem.loadPublicKey(Path(\"server.pub\"))\nval certs = Pem.readCertificateChain(Path(\"chain.crt\"))\nval keyStore = Pem.loadKeyStore(Path(\"server.crt\"), Path(\"server.key\"))\nval trustStore = Pem.loadTrustStore(Path(\"ca.crt\"))\n\n// Encode — .pem extension on all major types\npublicKey.pem                              // -----BEGIN PUBLIC KEY-----\nprivateKey.pem                             // -----BEGIN PRIVATE KEY-----\ncertificate.pem                            // -----BEGIN CERTIFICATE-----\ncsr.pem                                    // -----BEGIN CERTIFICATE REQUEST-----\ncrl.pem                                    // -----BEGIN X509 CRL-----\n\n// PKCS#8 export (encrypted \u0026 unencrypted)\nprivateKey.toPkcs8Pem()                    // -----BEGIN PRIVATE KEY-----\nprivateKey.toPkcs8Pem(password = \"secret\") // -----BEGIN ENCRYPTED PRIVATE KEY-----\n\n// PKCS#1 export (RSA only)\nrsaPrivateKey.toPkcs1Pem()                 // -----BEGIN RSA PRIVATE KEY-----\n```\n\n### KeyStore\n\n```kotlin\n// Parse a Base64-encoded PKCS#12 keystore into PEM components\nval bundle = parseKeyStore(base64Data, storePass = \"changeit\")\n// Export with encrypted PKCS#8 key\nval encrypted = parseKeyStore(base64Data, \"changeit\", format = KeyFormat.Pkcs8(keyPass = \"secret\"))\n// Export with PKCS#1 key (RSA only, no encryption)\nval pkcs1 = parseKeyStore(base64Data, \"changeit\", format = KeyFormat.Pkcs1)\n\n// PemBundle fields\nbundle.key        // PEM-encoded private key\nbundle.cert       // PEM-encoded leaf certificate\nbundle.certChain  // PEM-encoded CA certificate chain\nbundle.keyPass    // key password\n```\n\n### CSR\n\n```kotlin\nval csr = Csr.create(\n    x500Name = \"CN=app.example.com,O=Acme\",\n    algorithmName = \"SHA256withRSA\",\n    keyPair = keyPair,\n    sans = [San.Dns(\"app.example.com\"), San.Ip(\"10.0.0.1\")],\n)\nprintln(csr.pem)\n```\n\n### CRL\n\n```kotlin\nval crl = Crl.build(\n    keyPair = caKeyPair,\n    issuer = X500Principal(\"CN=My CA,O=Acme\"),\n    thisUpdate = Clock.System.now(),\n    nextUpdate = Clock.System.now() + 30.days,\n    revokedSerials = [42L, 99L],\n)\n\ncert.isRevokedBy(crl)          // check revocation\nCrl.distributionPoints(cert)   // extract CRL URLs\n```\n\n### DER DSL\n\nType-safe Kotlin DSL for building ASN.1 DER-encoded structures:\n\n```kotlin\nval encoded: ByteArray = seq {\n    integer(1L)\n    boolean(true)\n    seq {\n        oid(\"2.5.29.14\")\n        octetString(byteArrayOf(0x01, 0x02))\n    }\n    utcTime(Clock.System.now())\n    explicitTag(0) { integer(2L) }\n}\n```\n\nAll standard ASN.1 types are supported: `integer`, `boolean`, `bitString`, `octetString`, `oid`,\n`utcTime`, `nullValue`, `tag`, `implicitTag`, `explicitTag`, `seq`, and `set`.\n\n### TLS\n\n```kotlin\n// Scan remote server certificates\nval chain = scanCertificates(\"github.com\")\nchain.forEach { println(\"${it.commonName} — expires ${it.expiryDateUtc}\") }\n\n```\n\n## Supported Types\n\n| Category       | Formats                                         |\n|----------------|-------------------------------------------------|\n| Private keys   | PKCS#8, PKCS#8 encrypted, PKCS#1 (RSA, DSA, EC) |\n| Public keys    | X.509/SPKI, PKCS#1 RSA                          |\n| Certificates   | X.509v3 (PEM \u0026 DER)                             |\n| CRLs           | X.509 CRL (PEM \u0026 DER)                           |\n| Key algorithms | RSA, EC (secp256r1, secp384r1, …), DSA          |\n| Cert builder   | EC keys (SHA256withECDSA)                       |\n\n## 🔧 Build \u0026 Test\n\n```bash\n$ ./kotlin build                # Build\n$ ./kotlin test                 # Test\n$ ./kotlin publish mavenLocal   # Publish to local Maven repository\n```\n\n## 📦 Release\n\nPush a version tag to publish to Maven Central and create a GitHub release:\n\n```bash\n$ git tag -am \"Release v1.0.0\" v1.0.0\n$ git push origin --tags\n```\n\n## Credits\n\nThanks to the [Airlift](https://github.com/airlift/airlift) project. The crypto and DER/PEM logic is adapted from its\nsecurity module, rewritten as idiomatic Kotlin without the Guava dependency.\n\n## License\n\nApache 2.0 — see [LICENSE](LICENSE) for details.\n\n\u003c!-- Badges --\u003e\n\n[gha_url]: https://github.com/sureshg/certkit/actions/workflows/build.yaml\n\n[gha_badge]: https://img.shields.io/github/actions/workflow/status/sureshg/certkit/build.yaml?branch=main\u0026style=flat\u0026logo=kotlin\u0026logoColor=3BEA62\u0026label=Kotlin%20Build\n\n[java_url]: https://www.azul.com/downloads/?version=java-25-lts\u0026package=jdk#zulu\n\n[java_img]: https://img.shields.io/badge/OpenJDK-25-e76f00?logo=openjdk\u0026logoColor=e76f00\n\n[kt_url]: https://github.com/JetBrains/kotlin/releases/latest\n\n[kt_img]: https://img.shields.io/github/v/release/Jetbrains/kotlin?include_prereleases\u0026color=7f53ff\u0026label=Kotlin\u0026logo=kotlin\u0026logoColor=7f53ff\n\n[test_url]: https://suresh.dev/certkit/reports/\n\n[test_img]: https://img.shields.io/badge/Test_Report-passing-4c1?logo=junit5\u0026logoColor=white\n\n[maven_url]: https://central.sonatype.com/artifact/dev.suresh.certkit/certkit\n\n[maven_img]: https://img.shields.io/maven-central/v/dev.suresh.certkit/certkit?logo=apachemaven\u0026logoColor=C71A36\u0026color=C71A36\u0026label=Maven%20Central\n\n[kt_toolchain_url]: https://kotlin-toolchain.org/dev/\n\n[kt_toolchain_img]: https://img.shields.io/badge/Build-Kotlin%20Toolchain-3BEA62?logo=kotlin\u0026logoColor=3BEA62\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsureshg%2Fcertkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsureshg%2Fcertkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsureshg%2Fcertkit/lists"}