{"id":35003761,"url":"https://github.com/konfigyr/konfigyr-crypto","last_synced_at":"2026-05-30T03:01:18.201Z","repository":{"id":191945007,"uuid":"685135998","full_name":"konfigyr/konfigyr-crypto","owner":"konfigyr","description":"Spring Boot Crypto library","archived":false,"fork":false,"pushed_at":"2026-05-22T20:34:50.000Z","size":727,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-22T22:29:12.780Z","etag":null,"topics":["crypto","cryptography","java","key-management","spring-boot","tink"],"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/konfigyr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"SUPPORT.md","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":"2023-08-30T15:36:07.000Z","updated_at":"2026-05-22T20:34:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"d6094435-3364-4b2a-aec5-e7612af4884a","html_url":"https://github.com/konfigyr/konfigyr-crypto","commit_stats":null,"previous_names":["konfigyr/konfigyr-crypto"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/konfigyr/konfigyr-crypto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konfigyr%2Fkonfigyr-crypto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konfigyr%2Fkonfigyr-crypto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konfigyr%2Fkonfigyr-crypto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konfigyr%2Fkonfigyr-crypto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/konfigyr","download_url":"https://codeload.github.com/konfigyr/konfigyr-crypto/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konfigyr%2Fkonfigyr-crypto/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33678271,"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-05-30T02:00:06.278Z","response_time":92,"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":["crypto","cryptography","java","key-management","spring-boot","tink"],"created_at":"2025-12-27T04:19:37.055Z","updated_at":"2026-05-30T03:01:18.185Z","avatar_url":"https://github.com/konfigyr.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Konfigyr Crypto\n\n![CI Build](https://github.com/konfigyr/konfigyr-crypto/actions/workflows/continuous-integration.yml/badge.svg)\n[![codecov](https://codecov.io/gh/konfigyr/konfigyr-crypto/graph/badge.svg?token=K76STH7L4L)](https://codecov.io/gh/konfigyr/konfigyr-crypto)\n[![Join the chat at https://gitter.im/konfigyr/konfigyr-crypto](https://badges.gitter.im/konfigyr/konfigyr-crypto.svg)](https://gitter.im/konfigyr/konfigyr-crypt?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![Latest Release](https://img.shields.io/maven-central/v/com.konfigyr/konfigyr-crypto-api.svg?style=flat)](https://central.sonatype.com/search?q=g%3Acom.konfigyr)\n![Java 21+](https://img.shields.io/badge/java-21+-lightgray.svg)\n\nThe Konfigyr Crypto library defines instructs how should a Spring Application perform crypto operations, generate cryptographic material and manage its lifecycle. It attempts to define an API that best describes cryptography best practices how should protect your data and protect the encryption keys that protect your data.\n\nKonfigyr Crypto does not implement nor provides any direct cryptographic implementations, its goal is to provide an API *how* should those libraries be incorporated into an application. We recommend using well established cryptography libraries to perform cryptographic operations, such as [Google Tink](https://github.com/tink-crypto/tink-java) or [BouncyCastle](https://www.bouncycastle.org/documentation.html).\n\nLibrary enforces a two-tier approach, a recommended industry standard, to encrypting data. In a two-tier approach there are two types of encryption keys. First is the key you used to encrypt data, usually referred to as a *Data Encryption Key (DEK)*. The second key that is only used to encrypt the DEKs, referred to as a Master Key or Key Encryption Key (KEK), that generates the *Encrypted Data Encryption Key (eDEK)* which can than safely be stored in a persistent storage like a database or a file system.\n\nWhere possible, Key Encryption Keys should be stored in a separate location from Encrypted Data Encryption Key. For example, if the DEK is stored in a database, the KEK should be stored in the filesystem. This means that if an attacker only has access to one of these (for example through directory traversal or SQL injection), they cannot access both the keys and the data.\n\nIt is recommended that your Key Encryption Keys are managed by an external Key Management Service where wrapping and unwrapping of the DEKs occurs on the KMS servers . This way the private key material of the KEK is not known to your application making your system more resilient to attackers.\n\n## Key concepts\n\nThe goal of this library is not re-implement the wheel when it comes to cryptography, but rather to define a Java API how should a client application encrypt data and manage the keys that are used to encrypt it.\n\nLet's break down the library into couple of most used types and services:\n* `Keyset` - represents the Data Encryption Key (DEK)\n* `EncryptedKeyset` - represents the encrypted Data Encryption Key (eDEK)\n* `KeyEncryptionKey` - well, the name says it\n* `KeysetFactory` - generates the keysets used to encrypt the data\n* `KeysetStore` - used to generate, read and manipulate keysets or DEKs\n* `KeysetRepository` - used to read and store the encrypted DEKs\n\n### Keyset and Keyset factories\n\nThe `Keyset` is the focal point when working with this library. They represent a collection of keys which are performing certain cryptographic operations that is defined by its `Algorithm`.\n\nHere is an implementation example of Spring `BytesEncryptor` interface that uses a `Keyset`:\n\n```java\npublic class KeysetBytesEncryptor {\n\n    private final Keyset keyset;\n\n    @Override\n    public byte[] encrypt(byte[] byteArray) {\n        return keyset.encrypt(new ByteArray(byteArray)).array();\n    }\n\n    @Override\n    public byte[] decrypt(byte[] encryptedByteArray) {\n        return keyset.decrypt(new ByteArray(encryptedByteArray)).array();\n    }\n\n}\n```\n\nThe implementation of the `Keyset` and how the cryptographic operations are performed is the job of the `KeysetFactory`. This interface bridges the gap between the Konfigyr Crypto API and the actual cryptography library that would generate the key material and define how should it be used.\n\nFactories should be able to:\n* generate new keysets based upon the `Algorithm` that they define and support\n* wrap, or encrypt, the keysets before they are stored by the repository\n* unwrap, or decrypt, the encrypted keysets before they can be used\n\nKonfigyr Crypto comes with the following implementations of the `KeysetFactory` which you can use:\n * [Google Tink](konfigyr-crypto-tink)\n * [Nimbus JOSE JWT](konfigyr-crypto-jose)\n\n### Algorithms\n\nAn `Algorithm` is an immutable value object that declares the identity and capabilities of a cryptographic algorithm:\n\n* `name()` — a stable, unique identifier that is **persisted** alongside the `EncryptedKeyset`. It must never change once key material has been created with it.\n* `purpose()` — the `KeysetPurpose` (`SIGNING` or `ENCRYPTION`), which determines which operations the keyset supports.\n* `type()` — the `KeyType` of the underlying key material (`EC`, `RSA`, or `OCTET`).\n\nThe built-in `TinkAlgorithm` and `JoseAlgorithm` constants follow a naming convention of prefixing names with the library family (`tink:` and `jose:` respectively). Use a similar stable prefix for any custom algorithms to avoid name collisions.\n\n#### AlgorithmRegistry\n\nThe `AlgorithmRegistry` is a sealed catalog of all algorithms known to the application. It serves two purposes:\n\n1. **Resolution** — converts the algorithm name stored in an `EncryptedKeyset` back to the concrete `Algorithm` instance needed to decrypt it.\n2. **Algorithm confusion prevention** — only algorithms registered at startup can be resolved. An `EncryptedKeyset` referencing an unknown name will fail fast rather than attempting to use an unexpected algorithm.\n\nThe registry is sealed after the Spring context finishes initialising all singletons. Any attempt to register an algorithm after that point throws `IllegalStateException`.\n\n#### AlgorithmRegistrar\n\nAlgorithms are contributed to the registry via `AlgorithmRegistrar` beans. Each built-in module registers its algorithms during auto-configuration:\n\n```java\n@Bean\nAlgorithmRegistrar joseAlgorithmRegistrar() {\n    return registry -\u003e JoseAlgorithm.DEFAULT_ALGORITHMS.forEach(registry::register);\n}\n```\n\nDeclare your own `AlgorithmRegistrar` bean to add custom algorithms alongside the built-in ones.\n\n### Key encryption keys and providers\n\nThe `KeyEncryptionKey` is provided by the `KeyEncryptionKeyProvider`, there needs to be at least one provider with at least one KEK in order to use this library to generate the `Keyset`.\n\nHere is an example how you can define a `KeyEncryptionKeyProvider` as Spring Bean which uses a randomly generated Tink based `KeyEncryptionKey`:\n\n```java\nclass KeyEncryptionKeyProviderConfiguration {\n\n    @Bean\n    KeyEncryptionKeyProvider myKeyEncryptionKeyProvider() {\n        return KeyEncryptionKeyProvider.of(\"my-kek-provider\", List.of(\n                TinkKeyEncryptionKey.builder(\"my-kek-provider\").generate(\"my-kek\")\n        ));\n    }\n\n}\n```\n\nWhen using the `konfigyr-crypto-tink`, it is recommended to use a `KmsClient` with envelope encryption as your `KeyEncryptionKey`. Tink comes with Google and AWS KMS client implementations by you can easily create your own implementation of the `KmsClient`. Please refer to the [Google Tink Documentation](https://developers.google.com/tink) how they are used or implemented.\n\nHere is an example of using AWS KMS to declare a `KeyEncryptionKey`:\n\n```java\nclass KeyEncryptionKeyProviderConfiguration {\n\n    @Bean\n    KeyEncryptionKeyProvider myKeyEncryptionKeyProvider() {\n        return KeyEncryptionKeyProvider.of(\"my-kek-provider\", List.of(\n                TinkKeyEncryptionKey.builder(\"my-kek-provider\").generate(\"my-kek\")\n        ));\n    }\n\n    @Bean\n    KeyEncryptionKeyProvider kmsKeyEncryptionKeyProvider() {\n        return KeyEncryptionKeyProvider.of(\"kms-provider\", List.of(\n                TinkKeyEncryptionKey.builder(\"kms-provider\").kms(\n                        \"aws-kms://arn:aws:kms:us-west-2:account-id:key/key-id\", // KEK ID is the same as the key ARN\n                        \"AES256_GCM\" // algorithm used to create the DEK for the Keyset\n                )\n        ));\n    }\n\n}\n```\n\n\n### Keyset store\n\nStore is a Spring Bean which the application developers would use to interact with their Data Encryption Keys or DEKs. It bridges the actual cryptography and storage implementations in one place.\n\nWhen you are retrieving a `Keyset` the store would retrieve the `EncryptedKeyset`, find which `KeyEncryptionKey` was used to wrap it and unwrap and construct it using the responsible `KeysetFactory`.\n\nHere is an example how to create a `Keyset` based `BytesEncryptor` implementation using the `KeysetStore`\n\n```java\nclass KeysetBytesEncryptorFactory {\n    private final KeysetStore store;\n\n    public KeysetBytesEncryptor create(String keysetName) {\n        return new KeysetBytesEncryptor(store.read(keysetName));\n    }\n\n}\n```\n\nThe reversed process is applied when you wish to generate or update the `Keyset`, it would wrap the keys using the responsible `KeyEncryptionKey` and store the `KeyEncryptionKey` using the defined `KeysetRepository` implementation.\n\nHere is an example how a new Tink keyset is created, rotated or removed:\n\n```java\nclass TinkExample {\n    private final KeysetStore store;\n\n    public Keyset create() {\n        return store.create(\"my-kek-provider\", \"my-kek\", KeysetDefinition.of(\n                \"my-dek\", // give a name to your DEK\n                TinkAlgorithm.AES256_GCM // define the Tink algorithm to the DEK\n        ));\n    }\n\n    public Keyset createWithKek() {\n        final KeyEncryptionKey kek = store.kek(\"my-kek-provider\", \"my-kek\");\n\n        return store.create(kek, KeysetDefinition.of(\n                \"my-dek\", // give a name to your DEK\n                TinkAlgorithm.AES256_GCM // define the Tink algorithm to the DEK\n        ));\n    }\n\n    public void rotate() {\n        store.rotate(\"my-dek\");\n    }\n\n    public void remove() {\n        store.remove(\"my-dek\");\n    }\n}\n```\n\n### Key lifecycle management\n\nEach `EncryptedKey` within a keyset carries a `KeyStatus` that describes its position in the lifecycle state machine:\n\n| Status | Description |\n|---|---|\n| `ENABLED` | Active; participates in cryptographic operations |\n| `DISABLED` | Administratively deactivated; no cryptographic operations permitted |\n| `COMPROMISED` | Key material suspected or confirmed exposed; permanently blocked |\n| `PENDING_DESTRUCTION` | Scheduled for erasure; currently in its grace period |\n| `DESTROYED` | Key material permanently erased; row retained for audit |\n\n`KeysetStore` exposes methods to drive each transition:\n\n- `disable(keysetName, keyId)` — `ENABLED` → `DISABLED`\n- `enable(keysetName, keyId)` — `DISABLED` → `ENABLED`\n- `compromise(keysetName, keyId)` — emergency transition; permanently blocks the key for all cryptographic operations\n- `scheduleDestruction(keysetName, keyId)` — `DISABLED` or `COMPROMISED` → `PENDING_DESTRUCTION`, using the keyset's configured grace period (destroys immediately when no grace period is set)\n- `scheduleDestruction(keysetName, keyId, Instant)` — same, with an explicit destruction time\n- `cancelDestruction(keysetName, keyId)` — `PENDING_DESTRUCTION` → `DISABLED`\n- `destroy(keysetName, keyId)` — `PENDING_DESTRUCTION` → `DESTROYED`; erases key material but retains the row for audit\n\n```java\n// disable the old primary key after rotating to a new one\nstore.disable(\"my-dek\", oldKey.getId());\n\n// schedule it for destruction using the keyset's configured grace period\nstore.scheduleDestruction(\"my-dek\", oldKey.getId());\n```\n\n### Keyset repository\n\nKeyset repository is a simple interface which goal is to implement how should an `EncryptedKeyset` be stored, retrieved or removed.\n\nEvery `EncryptedKeyset` carries a version counter managed by the repository. Both `write()` and `updateKeyStatus()` check this counter and throw `CryptoException.KeysetConcurrentModificationException` when a concurrent modification is detected. Always cache and use the `EncryptedKeyset` returned by `write()` — not the input — so that the correct version is carried into the next write.\n\nKonfigyr Crypto comes with the following implementations of the `KeysetRepository` which you can use:\n* [JDBC](konfigyr-crypto-jdbc)\n\n### Scheduled maintenance: rotation and destruction\n\n`KeysetRepository` exposes two query methods designed for use in scheduled maintenance tasks.\n\n`findPendingRotation()` returns partial keysets (metadata only, empty key list) whose primary key's expiry time has elapsed. Call `store.rotate(name)` for each result:\n\n```java\nfor (EncryptedKeyset keyset : repository.findPendingRotation()) {\n    store.rotate(keyset.getName());\n}\n```\n\n`findPendingDestruction()` returns partial keysets (metadata and only the eligible pending-destruction keys) where `destructionScheduledAt` is in the past. Call `store.destroy(name, keyId)` for each key:\n\n```java\nfor (EncryptedKeyset keyset : repository.findPendingDestruction()) {\n    for (EncryptedKey key : keyset) {\n        store.destroy(keyset.getName(), key.getId());\n    }\n}\n```\n\nBoth methods return an empty list by default; repositories that can issue an efficient query — such as `JdbcKeysetRepository` — override them.\n\nWhen both a `KeysetStore` and a `KeysetRepository` bean are present in the application context, `KeysetTaskAutoConfiguration` registers both tasks automatically and enables Spring scheduling. Each task runs on a fixed-rate trigger every **1 hour** by default.\n\nTasks are configured under the `konfigyr.crypto.tasks` prefix. Each task name is a key in the map (`keyset-rotation` or `keyset-destruction`) and supports three properties:\n\n| Property | Type | Default | Description |\n|---|---|---|---|\n| `enabled` | `boolean` | `true` | Set to `false` to disable the task entirely |\n| `interval` | `Duration` | `PT1H` | Fixed-rate period between executions |\n| `cron` | `String` | — | Cron expression; when set, takes precedence over `interval` |\n\nWhen both `cron` and `interval` are configured for the same task, `cron` takes precedence and a warning is logged at startup.\n\n```properties\n# run rotation every night at 02:00\nkonfigyr.crypto.tasks.keyset-rotation.cron=0 0 2 * * *\n\n# run destruction every 30 minutes\nkonfigyr.crypto.tasks.keyset-destruction.interval=PT30M\n\n# disable rotation scheduling entirely (e.g. handled externally)\nkonfigyr.crypto.tasks.keyset-rotation.enabled=false\n```\n\n## Implementing a custom crypto provider\n\nTo integrate a new cryptography library or add a custom algorithm, you need three things:\n\n1. An `Algorithm` implementation that declares the algorithm's identity.\n2. A `Keyset` implementation that performs the actual cryptographic operations.\n3. A `KeysetFactory` implementation that creates `Keyset` instances from definitions and encrypted data.\n\nWire them as Spring beans and register your algorithms via `AlgorithmRegistrar`.\n\n### Step 1: Define your algorithm\n\n```java\npublic final class MyAlgorithm implements Algorithm {\n\n    public static final MyAlgorithm MY_SIGNING = new MyAlgorithm(\n        \"my-lib:EC_SIGNING\", KeysetPurpose.SIGNING, KeyType.EC\n    );\n\n    private final String name;\n    private final KeysetPurpose purpose;\n    private final KeyType type;\n\n    public MyAlgorithm(String name, KeysetPurpose purpose, KeyType type) {\n        this.name = name;\n        this.purpose = purpose;\n        this.type = type;\n    }\n\n    @Override public String name()           { return name; }\n    @Override public KeysetPurpose purpose() { return purpose; }\n    @Override public KeyType type()          { return type; }\n}\n```\n\nThe `name` is persisted in the `EncryptedKeyset` row and used to look up the algorithm at load time. Choose a stable prefix unique to your library (e.g. `my-lib:`) and never rename an algorithm once key material has been created with it.\n\n### Step 2: Implement KeysetFactory\n\n```java\npublic class MyKeysetFactory implements KeysetFactory {\n\n    public static final String NAME = \"my-lib\";\n\n    private final AlgorithmRegistry registry;\n\n    public MyKeysetFactory(AlgorithmRegistry registry) {\n        this.registry = registry;\n    }\n\n    @Override\n    public boolean supports(KeysetDefinition definition) {\n        // the definition carries the Algorithm object directly\n        return definition.getAlgorithm() instanceof MyAlgorithm;\n    }\n\n    @Override\n    public boolean supports(EncryptedKeyset encryptedKeyset) {\n        // match by the factory name stored in the encrypted keyset\n        return NAME.equals(encryptedKeyset.getFactory());\n    }\n\n    @Override\n    public Keyset create(KeyEncryptionKey kek, KeysetDefinition definition) {\n        MyAlgorithm algorithm = (MyAlgorithm) definition.getAlgorithm();\n        // generate key material using your library, return a Keyset implementation\n    }\n\n    @Override\n    public EncryptedKeyset create(Keyset keyset) throws IOException {\n        final List\u003cEncryptedKey\u003e encryptedKeys = new ArrayList\u003c\u003e();\n        for (Key key : keyset) {\n            final ByteArray serialized = // serialize this key to bytes using your library\n            final ByteArray wrapped = keyset.getKeyEncryptionKey().wrap(serialized);\n            encryptedKeys.add(EncryptedKey.from(key, WrappedKeyMaterial.of(wrapped)));\n        }\n        return EncryptedKeyset.from(keyset, encryptedKeys);\n    }\n\n    @Override\n    public Keyset create(KeyEncryptionKey kek, EncryptedKeyset encryptedKeyset) throws IOException {\n        for (EncryptedKey key : encryptedKeyset) {\n            final MyAlgorithm algorithm = (MyAlgorithm) registry.resolve(key.getAlgorithm());\n            // unwrap key.getData() using kek, then deserialize into your Keyset\n        }\n        // return a Keyset implementation\n    }\n}\n```\n\n`supports(EncryptedKeyset)` identifies ownership by the factory name stored on the keyset. `supports(KeysetDefinition)` can use `instanceof` because the definition already holds the `Algorithm` object directly.\n\n### Step 3: Register and wire as Spring beans\n\n```java\n@Configuration\nclass MyLibAutoConfiguration {\n\n    @Bean\n    AlgorithmRegistrar myAlgorithmRegistrar() {\n        return registry -\u003e registry.register(MyAlgorithm.MY_SIGNING);\n    }\n\n    @Bean\n    MyKeysetFactory myKeysetFactory(AlgorithmRegistry registry) {\n        return new MyKeysetFactory(registry);\n    }\n}\n```\n\nThe `KeysetStore` auto-configuration picks up all `KeysetFactory` beans automatically. Once these beans are declared, `store.create(kek, KeysetDefinition.of(\"my-key\", MyAlgorithm.MY_SIGNING))` will delegate to your factory without any further wiring.\n\n## Building from Source\nKonfigyr Crypto uses a Gradle-based build system. In the instructions below, `./gradlew` is invoked from the root of the source tree and serves as a cross-platform, self-contained bootstrap mechanism for the build.\n\n### Prerequisites\nGit and JDK 21.\n\n### Check out sources\n```shell\ngit clone git@github.com:konfigyr/konfigyr-crypto.git\n```\n\n### Publish to your local Maven repository\n```shell\n./gradlew publishToMavenLocal\n```\n\n### Compile and test\n```shell\n./gradlew build\n```\n\nDiscover more commands with `./gradlew tasks`.\n\n## Getting Support\nTry reaching out to the maintainers in our [Gitter chat](https://gitter.im/konfigyr/konfigyr-crypt). Commercial support is available too.\n\n## Contributing\n[Pull requests](https://help.github.com/articles/creating-a-pull-request) are more than welcome; see the [contributor](CONTRIBUTING.md) guidelines for details.\n\n## License\nKonfigyr Crypto library is Open Source software released under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkonfigyr%2Fkonfigyr-crypto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkonfigyr%2Fkonfigyr-crypto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkonfigyr%2Fkonfigyr-crypto/lists"}