{"id":33902269,"url":"https://github.com/eignex/kpermute","last_synced_at":"2026-04-27T10:00:43.871Z","repository":{"id":322325395,"uuid":"1089054987","full_name":"Eignex/kpermute","owner":"Eignex","description":"Kotlin library for shuffling lists too big for memory or for ID obfuscation. Using bijective integer permutations with fast cycle-walking hash mixing.","archived":false,"fork":false,"pushed_at":"2026-04-23T06:42:11.000Z","size":224,"stargazers_count":18,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-23T08:26:49.714Z","etag":null,"topics":["algorithm","bijective-permutation","data-masking","integer-permutation","kotlin","kotlin-library","kotlin-multiplatform","permutation","shuffling"],"latest_commit_sha":null,"homepage":"https://eignex.com/","language":"Kotlin","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/Eignex.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,"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":"2025-11-03T20:28:52.000Z","updated_at":"2026-04-23T06:42:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Eignex/kpermute","commit_stats":null,"previous_names":["rasros/kpermute","eigenity/kpermute","eignex/kpermute"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/Eignex/kpermute","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eignex%2Fkpermute","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eignex%2Fkpermute/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eignex%2Fkpermute/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eignex%2Fkpermute/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Eignex","download_url":"https://codeload.github.com/Eignex/kpermute/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eignex%2Fkpermute/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32331305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"online","status_checked_at":"2026-04-27T02:00:06.769Z","response_time":128,"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":["algorithm","bijective-permutation","data-masking","integer-permutation","kotlin","kotlin-library","kotlin-multiplatform","permutation","shuffling"],"created_at":"2025-12-12T00:16:20.137Z","updated_at":"2026-04-27T10:00:43.853Z","avatar_url":"https://github.com/Eignex.png","language":"Kotlin","readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://eignex.com/\"\u003e\n    \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/Eignex/.github/refs/heads/main/profile/banner-white.svg\"\u003e\n      \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/Eignex/.github/refs/heads/main/profile/banner.svg\"\u003e\n      \u003cimg alt=\"Eignex\" src=\"https://raw.githubusercontent.com/Eignex/.github/refs/heads/main/profile/banner.svg\" style=\"max-width: 100%; width: 22em;\"\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# KPermute\n\nFast, deterministic integer permutation library for Kotlin.\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.eignex/kpermute.svg?label=Maven%20Central)](https://central.sonatype.com/artifact/com.eignex/kpermute)\n[![Build](https://github.com/eignex/kpermute/actions/workflows/build.yml/badge.svg)](https://github.com/eignex/kpermute/actions/workflows/build.yml)\n[![codecov](https://codecov.io/gh/eignex/kpermute/branch/main/graph/badge.svg)](https://codecov.io/gh/eignex/kpermute)\n[![License](https://img.shields.io/github/license/eignex/kpermute)](https://github.com/eignex/kpermute/blob/main/LICENSE)\n\n\u003e Shuffle or obfuscate large integer domains efficiently using bijective,\n\u003e reversible hash mixing.\n\n**Not intended for cryptographic use.**\nSuitable for data masking, sampling, and reproducible pseudo-randomization\nwhere reversibility is required. You decide if your use-case is cryptographic.\n\n---\n\n## Overview\n\nkpermute generates stable, deterministic pseudo-random permutations over\ninteger ranges. Each seed defines a unique bijection between `[0, size)`.\n\nThe result acts like a keyed shuffle, repeatable, memory-efficient, and\ninvertible.\n\nTypical use cases:\n\n- Repeatable pseudo-random shuffles\n- Obfuscating integer IDs (e.g., user IDs, session numbers)\n- Collision-free sampling or load balancing\n- Data masking for non-sensitive identifiers\n\n---\n\n## Installation\n\nAdd the dependency from Maven Central:\n\n```kotlin\nimplementation(\"com.eignex:kpermute:1.1.2\")\n```\n\n---\n\n## Example Usage\n\n### Obfuscate numeric IDs reproducibly\n\n```kotlin\nval idPerm = longPermutation(seed = 1L)\nval longId = 49102490812045L\nval encoded = idPerm.encode(longId)\nprintln(\"encoded: $encoded (always prints 3631103739497407856)\")\n```\n\n### Shuffle a large list lazily\n\n```kotlin\nval largeList = object : AbstractList\u003cInt\u003e() {\n    override val size: Int get() = Int.MAX_VALUE\n    override fun get(index: Int) = index\n}\nval perm = intPermutation(largeList.size)\nval shuffled = largeList.permuted(perm)\nprintln(\"shuffled: ${shuffled.take(20)}\")\nval unshuffled = shuffled.unpermuted(perm)\nprintln(\"unshuffled: ${unshuffled.take(20)}\")\n```\n\n### Custom range permutation with negatives\n\n```kotlin\nval rangePerm = intPermutation(-100..199)\nprintln(\"encode(-50): ${rangePerm.encode(-50)}\")\nprintln(\"decode(...): ${rangePerm.decode(rangePerm.encode(-50))}\")\n```\n\n### Full 2^32-bit domain permutation\n\n```kotlin\nval fullPerm = intPermutation(-1, seed = 1L)\nprintln(fullPerm.encode(0)) // 1339315335\nprintln(fullPerm.encode(1)) // -897806455\n```\n\n---\n\n## How It Works\n\nKPermute builds **keyed, reversible permutations** over integer domains using\nxor-shift-multiply mixers and cycle-walking.\nIt never stores lookup tables and always supports decoding back to the original\nvalue.\n\n### Domains and Implementations\n\nEach permutation has a `size`:\n\n* `size \u003e 0` → finite domain `[0, size)`\n* `size == -1` / `-1L` → full 32- or 64-bit domain\n* `size \u003c 0` (not `-1`) → unsigned variants via `UIntPermutation` /\n  `ULongPermutation`\n\nFactory functions select implementations:\n\n| Domain Type       | Implementation               | Description                     |\n|-------------------|------------------------------|---------------------------------|\n| Tiny (`≤16`)      | `Array[Int/Long]Permutation` | Uses shuffled array and inverse |\n| Finite            | `Half[Int/Long]Permutation`  | Uses cycle-walking              |\n| Full bit-width    | `Full[Int/Long]Permutation`  | No cycle-walking                |\n| Unsigned variants | `U[Int/Long]Permutation`     | Modulo `2^32` or `2^64`         |                                 |\n\nRange factories like `intPermutation(range)` and `longPermutation(range)` wrap\nthese with a `range(...)` view, so you can permute directly on intervals such as\n`-100..199`.\n\n---\n\n### Mixing and Cycle-Walking\n\nEach permutation round:\n\n1. Multiplies by an odd constant.\n2. Adds or xors a secret per-round key.\n3. Applies xor-shift steps (`x ^= x \u003e\u003e\u003e s`) to diffuse bits.\n\nAll steps are invertible using modular inverses and xor-shift\ninversion [1] [3] [4] [5].\nFor non-power-of-two domains, KPermute uses **cycle-walking** [1] [2]: permute\nin\nthe next power-of-two space and retry until the output falls in `[0, size)`.\n\n---\n\n## References\n\n[1]: https://web.cs.ucdavis.edu/~rogaway/papers/subset.pdf\n\n[2]: https://csrc.nist.gov/csrc/media/projects/block-cipher-techniques/documents/bcm/proposed-modes/ffx/ffx-spec.pdf\n\n[3]: https://www-cs-faculty.stanford.edu/~knuth/taocp.html\n\n[4]: http://burtleburtle.net/bob/hash/integer.html\n\n[5]: https://arxiv.org/pdf/1402.6246.pdf\n\n[6]: https://github.com/Cyan4973/xxHash\n\n1. P. Rogaway and T. Shrimpton,\n   “Ciphers with Arbitrary Finite Domains,” *CT-RSA 2002*. [PDF][1]\n2. M. Bellare, P. Rogaway, and T. Spies,\n   “The FFX Mode of Operation for Format-Preserving Encryption,” *NIST\n   submission, 2010.* [Spec][2]\n3. D. E. Knuth,\n   *The Art of Computer Programming, Vol. 2: Seminumerical Algorithms,* 3rd ed.,\n    1997. [Info][3]\n4. B. Jenkins,\n   “Integer Hash Functions,” 1997. [Web][4]\n5. S. Vigna,\n   “An Experimental Exploration of Marsaglia’s Xorshift Generators, Scrambled,”\n   *TOMS 42(4), 2016.* [Preprint][5]\n6. Y. Collet,\n   “xxHash – Extremely fast hash algorithm,” 2014. [GitHub][6]\n\n---\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feignex%2Fkpermute","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feignex%2Fkpermute","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feignex%2Fkpermute/lists"}