{"id":19297443,"url":"https://github.com/factorhouse/shroud","last_synced_at":"2026-04-18T23:03:06.974Z","repository":{"id":55192104,"uuid":"452920071","full_name":"factorhouse/kpow-secure","owner":"factorhouse","description":"Key Generation and Payload Encryption","archived":false,"fork":false,"pushed_at":"2024-10-08T00:38:30.000Z","size":116,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-28T13:42:31.257Z","etag":null,"topics":["aes","clojure","config","encryption","java","kafka","kpow","pbkdf2"],"latest_commit_sha":null,"homepage":"","language":"Clojure","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/factorhouse.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2022-01-28T02:58:25.000Z","updated_at":"2024-10-08T00:38:33.000Z","dependencies_parsed_at":"2023-01-23T07:55:20.500Z","dependency_job_id":null,"html_url":"https://github.com/factorhouse/kpow-secure","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/factorhouse%2Fkpow-secure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/factorhouse%2Fkpow-secure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/factorhouse%2Fkpow-secure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/factorhouse%2Fkpow-secure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/factorhouse","download_url":"https://codeload.github.com/factorhouse/kpow-secure/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223893164,"owners_count":17220834,"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":["aes","clojure","config","encryption","java","kafka","kpow","pbkdf2"],"created_at":"2024-11-09T23:04:55.531Z","updated_at":"2025-12-12T01:33:59.956Z","avatar_url":"https://github.com/factorhouse.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shroud: Key Generation and Payload Encryption\n\n[![Kpow secure test](https://github.com/factorhouse/shroud/actions/workflows/ci.yml/badge.svg)](https://github.com/factorhouse/shroud/actions/workflows/ci.yml)\n[![Clojars Project](https://img.shields.io/clojars/v/io.factorhouse/shroud.svg)](https://clojars.org/io.factorhouse/shroud)\n\n\nA library for encrypted Kafka configuration with Java AES encryption and PBKDF2 master key generation.\n\nEncrypted configuration is **not a replacement for secret managers**, but may help in environments with limited secret management options.\n\nCan be used standalone or integrated with your application. This library provides:\n\n* [Clojure implementation](https://github.com/factorhouse/shroud/blob/main/README.md#clojure-implementation)\n* [Command line interface](https://github.com/factorhouse/shroud/blob/main/README.md#command-line-interface)\n\nThis library is used as an option to secure configuration for [Kpow for Apache Kafka](https://kpow.io) since [v88.2](https://kpow.io/releases/88-2/).\n\nSee the [Shroud Configuration Guide](https://github.com/factorhouse/kpow/tree/main/secure-config) for specifics on secure configuration for Kpow.\n\n## Capabilities\n\n * 256-bit AES encryption key generation from a passphrase and salt using PBKDF2WithHmacSHA256\n * AES/CBC/PKCS5Padding cipher-text with random IV encryption / decryption\n * Base64 key serialization / deserialization of keys for import / export\n * Base64 payload encoding of scheme version, IV length, IV, and cipher text\n * Payload interpretation (decrypt config into `java.util.Properties` or `clojure.lang.PersistentArrayMap`)\n * CLI interface for key generation and encryption / decryption\n * Java API for easy decryption of payload into `java.util.String` or `java.util.Properties`\n * Key lookup via SHROUD_KEY or SHROUD_KEY_LOCATION environment variables\n\n## License\n\nThis project is released under the MIT license.\n\n## Clojure Implementation\n\n### Key Generation\n\n#### Generate a key with a random salt (not reproducible from inputs)\n\n```clojure\n(key/secret-key \"aquickredfox\")\n```\n\n```clojure\n=\u003e #object[javax.crypto.spec.SecretKeySpec 0x9a9f63e \"javax.crypto.spec.SecretKeySpec@15b1a\"]\n```\n\n#### Generate a key with a chosen salt (reproducible from inputs)\n\n```clojure\n(key/secret-key \"aquickredfox\" \"asalt\")\n```\n\n```clojure\n=\u003e #object[javax.crypto.spec.SecretKeySpec 0x5c2ac756 \"javax.crypto.spec.SecretKeySpec@fffe96a4\"]\n```\n\n### Key Serialization\n\n#### Serialize a key to base64 text\n\n```clojure\n(key/export-key (key/secret-key \"aquickredfox\" \"asalt\"))\n```\n\n```clojure\n=\u003e \"Ic9cChI5tatKL1pzbQqVzJ0Tv0DsiEa7ES/CW1IVgok=\"\n```\n\n#### Produce a key from base64 text\n\n```clojure\n(key/import-key \"Ic9cChI5tatKL1pzbQqVzJ0Tv0DsiEa7ES/CW1IVgok=\")\n```\n\n```clojure\n=\u003e #object[javax.crypto.spec.SecretKeySpec 0x3d2b5928 \"javax.crypto.spec.SecretKeySpec@fffe96a4\"]\n```\n\n### Encryption\n\n#### Encrypted payload from base64 encoded key and plaintext\n\n```clojure\n(secure/encrypted\n \"//iQh9KYe7pM+mevjifZPrm7YE2+rRloG1E15zzjR88=\"\n (str \"SSL_KEYSTORE_PASSWORD=keypass1234\\n\"\n      \"SSL_TRUSTSTORE_PASSWORD=trustpass1234\"))\n```\n\n```clojure\n=\u003e \"ARAOGa3BAZ2TMxbU1aj+tFYfNHNwnRh3r/w2sG7FA4L7fVRzArpzrxAd2dUovyDfel++FHgW1IFrinZddTo+KiYFYm2rsn+ul65eQ1L5t9MsBq3LpuGjoFDSxkYFZweo/w0=\"\n```\n\n#### Encrypted payload from SecretKey and plaintext\n\n```clojure\n(secure/encoded-payload\n (key/secret-key \"aquickredfox\" \"some-salt\")\n (str \"SSL_KEYSTORE_PASSWORD=keypass1234\\n\"\n      \"SSL_TRUSTSTORE_PASSWORD=trustpass1234\"))\n```\n\n```clojure\n=\u003e \"ARAOGa3BAZ2TMxbU1aj+tFYfNHNwnRh3r/w2sG7FA4L7fVRzArpzrxAd2dUovyDfel++FHgW1IFrinZddTo+KiYFYm2rsn+ul65eQ1L5t9MsBq3LpuGjoFDSxkYFZweo/w0=\"\n```\n\n### Decryption\n\n#### Plaintext from serialized key and encrypted payload\n\n```clojure\n(secure/decrypted\n \"//iQh9KYe7pM+mevjifZPrm7YE2+rRloG1E15zzjR88=\"\n \"ARAOGa3BAZ2TMxbU1aj+tFYfNHNwnRh3r/w2sG7FA4L7fVRzArpzrxAd2dUovyDfel++FHgW1IFrinZddTo+KiYFYm2rsn+ul65eQ1L5t9MsBq3LpuGjoFDSxkYFZweo/w0=\")\n```\n\n```clojure\n=\u003e \"SSL_KEYSTORE_PASSWORD=keypass1234\\nSSL_TRUSTSTORE_PASSWORD=trustpass1234\"\n```\n\n#### Plaintext from SecretKey and encrypted payload\n\n```clojure\n(secure/decoded-text\n (key/secret-key \"aquickredfox\" \"some-salt\")\n \"ARAOGa3BAZ2TMxbU1aj+tFYfNHNwnRh3r/w2sG7FA4L7fVRzArpzrxAd2dUovyDfel++FHgW1IFrinZddTo+KiYFYm2rsn+ul65eQ1L5t9MsBq3LpuGjoFDSxkYFZweo/w0=\")\n```\n\n```clojure\n=\u003e \"SSL_KEYSTORE_PASSWORD=keypass1234\\nSSL_TRUSTSTORE_PASSWORD=trustpass1234\"\n```\n\n### Interpretation\n\nKpow-Secure will interpret payloads where the plaintext is in `java.util.Properties` format.\n\nSee [dev-resources/secure/props.env](dev-resources/secure/props.env) for an example of the flexibility of Java Properties encoding.\n\n#### Interpret payload as clojure.lang.PersistentArrayMap\n\n```clojure\n(-\u003e (secure/decrypted (slurp \"dev-resources/secure/passphrase.key\") (slurp \"dev-resources/secure/config.env.aes\"))\n    (secure/-\u003emap))\n```\n\n```\n=\u003e\n{\"SASL_JAAS_CONFIG\"        \"org.apache.kafka.common.security.plain.PlainLoginModule required username=\\\"kpow\\\" password=\\\"kpow-secret\\\";\"\n \"SASL_MECHANISM\"          \"PLAIN\"\n \"SECURITY_PROTOCOL\"       \"SASL_PLAINTEXT\"\n \"SSL_TRUSTSTORE_LOCATION\" \"/ssl/truststore.jks\"\n \"SSL_TRUSTSTORE_PASSWORD\" \"password1234\"}\n```\n\n#### Interpret payload as java.util.Properties\n\n```clojure\n(-\u003e (secure/decrypted (slurp \"dev-resources/secure/passphrase.key\") (slurp \"dev-resources/secure/props.env.aes\"))\n    (secure/-\u003eprops))\n```\n\n```clojure\n=\u003e\n{\"sasl.jaas.config\"        \"org.apache.kafka.common.security.plain.PlainLoginModule required username=\\\"kpow\\\" password=\\\"kpow-secret\\\";\"\n \"sasl.mechanism\"          \"PLAIN\"\n \"security.protocol\"       \"SASL_PLAINTEXT\"\n \"ssl.truststore.location\" \"/ssl/truststore.jks\"\n \"ssl.truststore.password\" \"1234\"}\n```\n\n## Command Line Interface\n\nThis library exposes key generation and payload encryption / decryption functions via a CLI.\n\nYou can uberjar this project, or include the library within your own project and uberjar that.\n\n### Key Generation\n\nThe passphrase is read from a local file to ensure it is not observable in your shell history.\n\n#### Show the help menu\n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud.key --help\n```\n\n```bash\n21:27:09.090 [main] INFO io.factorhouse.shroud.key -\n\n  -p, --pass-file PASSPHRASE-FILE  (required) File containing key passphrase\n  -s, --salt SALT                  (optional) Salt to use with key generation, random if none provided\n  -o, --out-file OUT-FILE          (optional) File for key output, default: [PASSPHRASE-FILE].key\n  -h, --help\n```\n\n#### Generate a key with random salt\n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud.key --pass-file dev-resources/secure/passphrase.txt --out-file dev-resources/secure/passphrase.key\n```\n\n```bash\n19:46:50.912 [main] INFO io.factorhouse.shroud.key -\n\nShroud Key:\n----------------\n\nnP+O/6xOu9+9+JZFYgfhS+R6x4OjVgToP9DlM1bx35g=\n\nKey file written to: dev-resources/secure/passphrase.key\n\nRandom salt used, this key cannot be regenerated.\n```\n\n#### Generate a key with chosen salt\n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud.key --pass-file dev-resources/secure/passphrase.txt --salt abcdef --out-file dev-resources/secure/mykey.aes\n```\n\n```bash\n19:48:01.933 [main] INFO io.factorhouse.shroud.key -\n\nShroud Key:\n----------------\n\n88wRMz4DuaRWOmyKPb8IgmY4kZAyQvPiRVxUy79OgL8=\n\nKey file written to: dev-resources/secure/mykey.aes\n\nThis key can be regenerated with the same passphrase and salt.\n```\n\n### Encryption\n\n#### Show the help menu\n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud --help\n```\n\n```bash\n23:01:46.551 [main] INFO io.factorhouse.shroud -\n\n      --key TEXT           Base64 encoded key\n      --key-file FILE      File containing base64 encoded key\n      --encrypt TEXT       Text to encrypt\n      --decrypt TEXT       Base64 encoded payload text\n      --encrypt-file FILE  File containing text to encrypt\n      --decrypt-file FILE  File containing base64 encoded payload text\n      --out-file FILE      (optional) File for encrypted/decrypted output\n  -h, --help\n```\n\n#### Encrypt text directly on the command line \n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud --encrypt supersecrettext --key 88wRMz4DuaRWOmyKPb8IgmY4kZAyQvPiRVxUy79OgL8=\n```\n\n```bash\n22:19:30.511 [main] INFO io.factorhouse.shroud -\n\nKpow Encrypted:\n---------------\n\nARB41R5ZsMNkjNnr3YD+RK2wT6ywAgR0KpcCpLYH/g3rxQ==\n```\n\n#### Decrypt text directly on the command line \n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud --decrypt ARDO7O0legO6PFvIGq/ILD/gekC43knuHqCxhvJoyOeCBw== --key-file dev-resources/secure/passphrase.key\n```\n\n```bash\n22:21:16.491 [main] INFO io.factorhouse.shroud -\n\nKpow Decrypted:\n---------------\n\nsupersecrettext\n```\n\n#### Encrypt a plaintext file\n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud --encrypt-file dev-resources/secure/config.env --key-file dev-resources/secure/passphrase.key --out-file dev-resources/secure/config.aes\n```\n\n```bash\n22:33:28.807 [main] INFO io.factorhouse.shroud -\n\nKpow Encrypted:\n---------------\n\n\u003e dev-resources/secure/config.aes\n```\n\n#### View the encrypted payload\n\n```bash\ncat dev-resources/secure/config.aes\n```\n\n```bash\nARD9I/BlocgOwYfsW/oXrJtY/u2AnMWm/ewWIm7iDJrSkkGnQbM38ZbCM1hWfYZLHpIo99LATlgtnR4rcSjDIEY01wZTsZUyxLXKMoH1sX31FwoywxjmGPooMQg2d6VIHpLGeTsrmD1HQ2U9miIr01w5moMy4U6/UTAm1o+f8xGmR5l2sMj59tddK5VTC9BRs0L4ptxj+bR/QhItwL2qnqExnsEBTUOwrrTiHZySXhr8iJWvD1WIFL374KmneLxFhqMuIiY1D3v9/ChlyCojvh5JR6pJ3ZuIK3HP2YbjZSTSliz7mV5hMI021E4MN8hWE4L3poLhHY5KWVVb6Ma5kQAt2M5t9Ij8HkdtjMgxrva+kCtXUg81F9WoWmsc3xQcY5o=\n```\n\n### Decryption\n\n#### Decrypt the payload\n\n```bash\njava -cp target/shroud-1.0.0-standalone.jar io.factorhouse.shroud --decrypt-file dev-resources/secure/config.aes --key-file dev-resources/secure/passphrase.key\n```\n\n```bash\n22:40:11.998 [main] INFO io.factorhouse.shroud -\n\nKpow Decrypted:\n---------------\n\nSECURITY_PROTOCOL=SASL_PLAINTEXT\nSASL_MECHANISM=PLAIN\nSASL_JAAS_CONFIG=org.apache.kafka.common.security.plain.PlainLoginModule required username=\"kpow\" password=\"kpow-secret\";\nSSL_TRUSTSTORE_LOCATION=/ssl/truststore.jks```\n```\n\n## License\n\nDistributed under the Apache 2.0 License.\n\nCopyright (c) [Factor House](https://factorhouse.io)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffactorhouse%2Fshroud","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffactorhouse%2Fshroud","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffactorhouse%2Fshroud/lists"}