pax_global_header00006660000000000000000000000064145663620360014525gustar00rootroot0000000000000052 comment=b3ac32866b11be88bdf348b51e51287555707438 zxcvbn-rs-py-0.1.1/000077500000000000000000000000001456636203600141065ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/.editorconfig000066400000000000000000000003171456636203600165640ustar00rootroot00000000000000# http://editorconfig.org root = true [*] indent_style = space indent_size = 2 trim_trailing_whitespace = true insert_final_newline = true charset = utf-8 end_of_line = lf [*.{py,pyi,rs}] indent_size = 4 zxcvbn-rs-py-0.1.1/.github/000077500000000000000000000000001456636203600154465ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/.github/workflows/000077500000000000000000000000001456636203600175035ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/.github/workflows/CI.yml000066400000000000000000000054111456636203600205220ustar00rootroot00000000000000# This file is autogenerated by maturin v1.4.0 # To update, run # # maturin generate-ci github # name: CI on: push: branches: - main - master tags: - '*' pull_request: workflow_dispatch: permissions: contents: read jobs: linux: runs-on: ubuntu-latest strategy: matrix: target: [x86_64, x86, aarch64, armv7, s390x, ppc64le] steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.10' - name: Build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} args: --release --out dist --find-interpreter sccache: 'true' manylinux: auto - name: Upload wheels uses: actions/upload-artifact@v3 with: name: wheels path: dist windows: runs-on: windows-latest strategy: matrix: target: [x64, x86] steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.10' architecture: ${{ matrix.target }} - name: Build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} args: --release --out dist --find-interpreter sccache: 'true' - name: Upload wheels uses: actions/upload-artifact@v3 with: name: wheels path: dist macos: runs-on: macos-latest strategy: matrix: target: [x86_64, aarch64] steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.10' - name: Build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} args: --release --out dist --find-interpreter sccache: 'true' - name: Upload wheels uses: actions/upload-artifact@v3 with: name: wheels path: dist sdist: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Build sdist uses: PyO3/maturin-action@v1 with: command: sdist args: --out dist - name: Upload sdist uses: actions/upload-artifact@v3 with: name: wheels path: dist release: name: Release runs-on: ubuntu-latest if: "startsWith(github.ref, 'refs/tags/')" needs: [linux, windows, macos, sdist] steps: - uses: actions/download-artifact@v3 with: name: wheels - name: Publish to PyPI uses: PyO3/maturin-action@v1 env: MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} with: command: upload args: --non-interactive --skip-existing * zxcvbn-rs-py-0.1.1/.github/workflows/documentation.yml000066400000000000000000000021111456636203600230720ustar00rootroot00000000000000name: Build documentation on: push: branches: - main # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write # Allow one concurrent deployment concurrency: group: "pages" cancel-in-progress: true # Default to bash defaults: run: shell: bash jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip pip install hatch hatch env create - name: Build run: hatch run docs-build - name: Upload artifact uses: actions/upload-pages-artifact@v1 with: path: ./site deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v1 zxcvbn-rs-py-0.1.1/.gitignore000066400000000000000000000012431456636203600160760ustar00rootroot00000000000000/target # Byte-compiled / optimized / DLL files __pycache__/ .pytest_cache/ *.py[cod] # C extensions *.so # Distribution / packaging .Python .venv/ env/ bin/ build/ develop-eggs/ dist/ eggs/ lib/ lib64/ parts/ sdist/ var/ include/ man/ venv/ *.egg-info/ .installed.cfg *.egg # Installer logs pip-log.txt pip-delete-this-directory.txt pip-selfcheck.json # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo # Mr Developer .mr.developer.cfg .project .pydevproject # Rope .ropeproject # Django stuff: *.log *.pot .DS_Store # Sphinx documentation docs/_build/ # PyCharm .idea/ # Pyenv .python-version venv*/ zxcvbn-rs-py-0.1.1/.vscode/000077500000000000000000000000001456636203600154475ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/.vscode/settings.json000066400000000000000000000011071456636203600202010ustar00rootroot00000000000000{ "python.analysis.typeCheckingMode": "basic", "python.analysis.autoImportCompletions": true, "python.terminal.activateEnvironment": true, "python.terminal.activateEnvInCurrentTerminal": true, "python.testing.unittestEnabled": false, "editor.rulers": [88], "python.defaultInterpreterPath": "${workspaceFolder}/.hatch/zxcvbn-rs-py/bin/python", "[python]": { "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": "explicit", "source.organizeImports": "explicit" }, "editor.defaultFormatter": "charliermarsh.ruff" } } zxcvbn-rs-py-0.1.1/Cargo.lock000066400000000000000000000405451456636203600160230ustar00rootroot00000000000000# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bit-set" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" version = "3.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "darling" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ "darling_core", "darling_macro", ] [[package]] name = "darling_core" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", "syn 1.0.109", ] [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ "darling_core", "quote", "syn 1.0.109", ] [[package]] name = "deranged" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] [[package]] name = "derive_builder" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ "darling", "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "derive_builder_macro" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" dependencies = [ "derive_builder_core", "syn 1.0.109", ] [[package]] name = "either" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "fancy-regex" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" dependencies = [ "bit-set", "regex", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indoc" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "js-sys" version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "lock_api" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets", ] [[package]] name = "portable-atomic" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53bdbb96d49157e65d45cc287af5f32ffadd5f4761438b527b055fb0d4bb8233" dependencies = [ "cfg-if", "indoc", "libc", "memoffset", "parking_lot", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", "unindent", ] [[package]] name = "pyo3-build-config" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deaa5745de3f5231ce10517a1f5dd97d53e5a2fd77aa6b5842292085831d48d7" dependencies = [ "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b42531d03e08d4ef1f6e85a2ed422eb678b8cd62b762e53891c05faf0d4afa" dependencies = [ "libc", "pyo3-build-config", ] [[package]] name = "pyo3-macros" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7305c720fa01b8055ec95e484a6eca7a83c841267f0dd5280f0c8b8551d2c158" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", "syn 2.0.50", ] [[package]] name = "pyo3-macros-backend" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c7e9b68bb9c3149c5b0cade5d07f953d6d125eb4337723c4ccdb665f1f96185" dependencies = [ "heck", "proc-macro2", "pyo3-build-config", "quote", "syn 2.0.50", ] [[package]] name = "quick-error" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags", ] [[package]] name = "regex" version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", "syn 2.0.50", ] [[package]] name = "smallvec" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "time" version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "num-conv", "powerfmt", "serde", "time-core", ] [[package]] name = "time-core" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unindent" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "wasm-bindgen" version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn 2.0.50", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", "syn 2.0.50", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "zxcvbn" version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "103fa851fff70ea29af380e87c25c48ff7faac5c530c70bd0e65366d4e0c94e4" dependencies = [ "derive_builder", "fancy-regex", "itertools", "js-sys", "lazy_static", "quick-error", "regex", "time", ] [[package]] name = "zxcvbn-rs-py" version = "0.1.1" dependencies = [ "pyo3", "zxcvbn", ] zxcvbn-rs-py-0.1.1/Cargo.toml000066400000000000000000000004121456636203600160330ustar00rootroot00000000000000[package] name = "zxcvbn-rs-py" version = "0.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "zxcvbn_rs_py" crate-type = ["cdylib"] [dependencies] pyo3 = "0.20.3" zxcvbn = "2.2.2" zxcvbn-rs-py-0.1.1/LICENSE000066400000000000000000000020471456636203600151160ustar00rootroot00000000000000MIT License Copyright (c) 2023, Fief Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. zxcvbn-rs-py-0.1.1/README.md000066400000000000000000000025361456636203600153730ustar00rootroot00000000000000# zxcvbn-rs-py

Python bindings for zxcvbn-rs, the Rust implementation of zxcvbn

[![build](https://github.com/fief-dev/zxcvbn-rs-py/workflows/CI/badge.svg)](https://github.com/fief-dev/zxcvbn-rs-py/actions) [![PyPI version](https://badge.fury.io/py/zxcvbn-rs-py.svg)](https://badge.fury.io/py/zxcvbn-rs-py) --- **Documentation**: https://fief-dev.github.io/zxcvbn-rs-py/ **Source Code**: https://github.com/fief-dev/zxcvbn-rs-py --- ## Installation ```sh pip install zxcvbn-rs-py ``` ## Quickstart ```py from zxcvbn_rs_py import zxcvbn r = zxcvbn("correcthorsebatterystaple") print(r.score) ``` ## Benchmark Thanks to its Rust core, zxcvbn-rs-py is **~5 times faster** than the pure Python implementation, [zxcvbn-python](https://github.com/dwolfhub/zxcvbn-python). ![zxcvbn-rs-py benchmark](https://raw.githubusercontent.com/fief-dev/zxcvbn-rs-py/main/benchmark/benchmark.svg?sanitize=true) ## Serve the documentation You can serve the Mkdocs documentation with: ```bash hatch run docs-serve ``` It'll automatically watch for changes in your code. ## License This project is licensed under the terms of the MIT license. zxcvbn-rs-py-0.1.1/benchmark/000077500000000000000000000000001456636203600160405ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/benchmark/benchmark.dat000066400000000000000000000004421456636203600204640ustar00rootroot00000000000000"Case" "zxcvbn" "zxcvbn_rs_py" "Length 4" 0.1059061661362648 0.00814666599035263 "Length 8" 0.33018958382308483 0.044096667785197496 "Length 16" 0.645416583865881 0.0927467499859631 "Length 32" 2.0843886681832373 0.3682430819608271 "Repetition" 0.8810213343240321 0.09670516801998019 zxcvbn-rs-py-0.1.1/benchmark/benchmark.svg000066400000000000000000000333451456636203600205230ustar00rootroot00000000000000 Gnuplot Produced by GNUPLOT 5.4 patchlevel 6 0 0.5 1 1.5 2 2.5 Length 4 Length 8 Length 16 Length 32 Repetition Milliseconds Test cases gnuplot_plot_1 zxcvbn gnuplot_plot_2 zxcvbn_rs_py zxcvbn-rs-py-0.1.1/benchmark/plot.plt000066400000000000000000000005721456636203600175430ustar00rootroot00000000000000set terminal svg size 1280,800 noenhanced background rgb 'white' set output 'benchmark/benchmark.svg' set style data histogram set style histogram cluster gap 1 set style fill solid border rgb "black" set auto x set yrange [0:*] set ylabel "Milliseconds" set xlabel "Test cases" plot 'benchmark/benchmark.dat' using 2:xtic(1) title col, \ '' using 3:xtic(1) title col zxcvbn-rs-py-0.1.1/benchmark/run.py000066400000000000000000000016511456636203600172210ustar00rootroot00000000000000import csv import timeit LIBRARIES = [ "zxcvbn", "zxcvbn_rs_py", ] PASSWORDS = { "Length 4": "igrI", "Length 8": "UzA170rl", "Length 16": "pvmXR8ECp10UIRCs", "Length 32": "MtvEJJUM2K0mKAyWKy0emf6Bt9xyxrru", "Repetition": "a" * 16, } NB_LOOP = 500 REPEAT = 5 with open("benchmark/benchmark.dat", "w") as file: writer = csv.writer(file, delimiter="\t", quoting=csv.QUOTE_NONNUMERIC) writer.writerow(("Case", *LIBRARIES)) for key, value in PASSWORDS.items(): row = [key] print(f"Run benchmark for {key}...") for library in LIBRARIES: result = min( timeit.repeat( f"zxcvbn('{value}')", setup=f"from {library} import zxcvbn", number=NB_LOOP, repeat=REPEAT, ) ) row.append(result / NB_LOOP * 1000) writer.writerow(row) zxcvbn-rs-py-0.1.1/benchmark/script.sh000077500000000000000000000003701456636203600177030ustar00rootroot00000000000000# !/bin/bash set -e VENV=venv-bench LIBRARIES=("zxcvbn" "zxcvbn-rs-py") rm -rf $VENV python -m venv $VENV for LIBRARY in ${LIBRARIES[@]} do ./$VENV/bin/pip install $LIBRARY done ./$VENV/bin/python benchmark/run.py gnuplot benchmark/plot.plt zxcvbn-rs-py-0.1.1/docs/000077500000000000000000000000001456636203600150365ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/docs/index.md000066400000000000000000000000231456636203600164620ustar00rootroot00000000000000--8<-- "README.md" zxcvbn-rs-py-0.1.1/docs/reference/000077500000000000000000000000001456636203600167745ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/docs/reference/zxcvbn_rs_py.md000066400000000000000000000005271456636203600220500ustar00rootroot00000000000000# Reference ::: zxcvbn_rs_py options: members: - CrackTimesDisplay - CrackTimesSeconds - Entropy - Feedback - Suggestion - Warning - zxcvbn show_root_heading: false show_source: false allow_inspection: false separate_signature: true show_if_no_docstring: true zxcvbn-rs-py-0.1.1/mkdocs.yml000066400000000000000000000031601456636203600161110ustar00rootroot00000000000000site_name: zxcvbn-rs-py site_description: zxcvbn password strength library for Python using Rust bindings repo_url: https://github.com/fief-dev/zxcvbn-rs-py repo_name: fief-dev/zxcvbn-rs-py theme: name: material icon: logo: material/key-chain-variant palette: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" scheme: default primary: black accent: amber toggle: icon: material/brightness-7 name: Switch to dark mode # Palette toggle for dark mode - media: "(prefers-color-scheme: dark)" scheme: slate primary: black accent: amber toggle: icon: material/brightness-4 name: Switch to light mode features: - navigation.instant - navigation.expand - navigation.indexes - navigation.top - search.suggest - search.highlight - content.code.copy markdown_extensions: - toc: permalink: true - pymdownx.highlight: anchor_linenums: true - pymdownx.tasklist: custom_checkbox: true - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences plugins: - search - mkdocstrings: handlers: python: paths: [./zxcvbn_rs_py] import: - https://docs.python.org/3.10/objects.inv options: docstring_style: google watch: - docs - zxcvbn_rs_py nav: - About: index.md - Reference: - zxcvbn_rs_py: reference/zxcvbn_rs_py.md zxcvbn-rs-py-0.1.1/pyproject.toml000066400000000000000000000022241456636203600170220ustar00rootroot00000000000000[build-system] requires = ["maturin>=1.4.0,<2.0.0"] build-backend = "maturin" [project] name = "zxcvbn-rs-py" authors = [ { name = "François Voron", email = "contact@fief.dev" } ] description = "Python bindings for zxcvbn-rs, the Rust implementation of zxcvbn" readme = "README.md" requires-python = ">=3.7,<3.13" dynamic = ["version"] classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Security", ] [project.urls] Documentation = "https://fief-dev.github.io/zxcvbn-rs-py/" Source = "https://github.com/fief-dev/zxcvbn-rs-py" [tool.maturin] features = ["pyo3/extension-module"] [tool.ruff.lint] extend-select = ["I", "TRY"] [tool.hatch] [tool.hatch.envs.default] python = "3.12" dependencies = [ "maturin", "mkdocs-material", "mkdocstrings[python]>=0.18", "black", "mypy", "ruff", ] [tool.hatch.envs.default.scripts] lint = [ "cargo fmt", "ruff format .", "ruff --fix .", ] lint-check = [ "ruff format --check .", "ruff .", ] docs-serve = "mkdocs serve" docs-build = "mkdocs build" zxcvbn-rs-py-0.1.1/src/000077500000000000000000000000001456636203600146755ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/src/lib.rs000066400000000000000000000355401456636203600160200ustar00rootroot00000000000000extern crate zxcvbn; use pyo3::exceptions::{PyRuntimeError, PyValueError}; use pyo3::prelude::*; use std::fmt; #[pyclass] #[pyo3(module = "zxcvbn_rs_py")] #[derive(Clone)] enum Warning { StraightRowsOfKeysAreEasyToGuess, ShortKeyboardPatternsAreEasyToGuess, RepeatsLikeAaaAreEasyToGuess, RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess, ThisIsATop10Password, ThisIsATop100Password, ThisIsACommonPassword, ThisIsSimilarToACommonlyUsedPassword, SequencesLikeAbcAreEasyToGuess, RecentYearsAreEasyToGuess, AWordByItselfIsEasyToGuess, DatesAreOftenEasyToGuess, NamesAndSurnamesByThemselvesAreEasyToGuess, CommonNamesAndSurnamesAreEasyToGuess, } impl fmt::Display for Warning { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Warning::StraightRowsOfKeysAreEasyToGuess => { write!(f, "Straight rows of keys are easy to guess.") } Warning::ShortKeyboardPatternsAreEasyToGuess => { write!(f, "Short keyboard patterns are easy to guess.") } Warning::RepeatsLikeAaaAreEasyToGuess => { write!(f, "Repeats like \"aaa\" are easy to guess.") } Warning::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess => write!( f, "Repeats like \"abcabcabc\" are only slightly harder to guess than \"abc\"." ), Warning::ThisIsATop10Password => write!(f, "This is a top-10 common password."), Warning::ThisIsATop100Password => write!(f, "This is a top-100 common password."), Warning::ThisIsACommonPassword => write!(f, "This is a very common password."), Warning::ThisIsSimilarToACommonlyUsedPassword => { write!(f, "This is similar to a commonly used password.") } Warning::SequencesLikeAbcAreEasyToGuess => { write!(f, "Sequences like abc or 6543 are easy to guess.") } Warning::RecentYearsAreEasyToGuess => write!(f, "Recent years are easy to guess."), Warning::AWordByItselfIsEasyToGuess => write!(f, "A word by itself is easy to guess."), Warning::DatesAreOftenEasyToGuess => write!(f, "Dates are often easy to guess."), Warning::NamesAndSurnamesByThemselvesAreEasyToGuess => { write!(f, "Names and surnames by themselves are easy to guess.") } Warning::CommonNamesAndSurnamesAreEasyToGuess => { write!(f, "Common names and surnames are easy to guess.") } } } } #[pymethods] impl Warning { fn __str__(&self) -> PyResult { return Ok(format!("{self}")); } } fn match_warning(warning: zxcvbn::feedback::Warning) -> Warning { match warning { zxcvbn::feedback::Warning::StraightRowsOfKeysAreEasyToGuess => { Warning::StraightRowsOfKeysAreEasyToGuess } zxcvbn::feedback::Warning::ShortKeyboardPatternsAreEasyToGuess => { Warning::ShortKeyboardPatternsAreEasyToGuess } zxcvbn::feedback::Warning::RepeatsLikeAaaAreEasyToGuess => { Warning::RepeatsLikeAaaAreEasyToGuess } zxcvbn::feedback::Warning::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess => { Warning::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess } zxcvbn::feedback::Warning::ThisIsATop10Password => Warning::ThisIsATop10Password, zxcvbn::feedback::Warning::ThisIsATop100Password => Warning::ThisIsATop100Password, zxcvbn::feedback::Warning::ThisIsACommonPassword => Warning::ThisIsACommonPassword, zxcvbn::feedback::Warning::ThisIsSimilarToACommonlyUsedPassword => { Warning::ThisIsSimilarToACommonlyUsedPassword } zxcvbn::feedback::Warning::SequencesLikeAbcAreEasyToGuess => { Warning::SequencesLikeAbcAreEasyToGuess } zxcvbn::feedback::Warning::RecentYearsAreEasyToGuess => Warning::RecentYearsAreEasyToGuess, zxcvbn::feedback::Warning::AWordByItselfIsEasyToGuess => { Warning::AWordByItselfIsEasyToGuess } zxcvbn::feedback::Warning::DatesAreOftenEasyToGuess => Warning::DatesAreOftenEasyToGuess, zxcvbn::feedback::Warning::NamesAndSurnamesByThemselvesAreEasyToGuess => { Warning::NamesAndSurnamesByThemselvesAreEasyToGuess } zxcvbn::feedback::Warning::CommonNamesAndSurnamesAreEasyToGuess => { Warning::CommonNamesAndSurnamesAreEasyToGuess } } } #[pyclass] #[pyo3(module = "zxcvbn_rs_py")] #[derive(Clone)] enum Suggestion { UseAFewWordsAvoidCommonPhrases, NoNeedForSymbolsDigitsOrUppercaseLetters, AddAnotherWordOrTwo, CapitalizationDoesntHelpVeryMuch, AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase, ReversedWordsArentMuchHarderToGuess, PredictableSubstitutionsDontHelpVeryMuch, UseALongerKeyboardPatternWithMoreTurns, AvoidRepeatedWordsAndCharacters, AvoidSequences, AvoidRecentYears, AvoidYearsThatAreAssociatedWithYou, AvoidDatesAndYearsThatAreAssociatedWithYou, } impl fmt::Display for Suggestion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Suggestion::UseAFewWordsAvoidCommonPhrases => { write!(f, "Use a few words, avoid common phrases.") } Suggestion::NoNeedForSymbolsDigitsOrUppercaseLetters => { write!(f, "No need for symbols, digits, or uppercase letters.") } Suggestion::AddAnotherWordOrTwo => { write!(f, "Add another word or two. Uncommon words are better.") } Suggestion::CapitalizationDoesntHelpVeryMuch => { write!(f, "Capitalization doesn't help very much.") } Suggestion::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase => write!( f, "All-uppercase is almost as easy to guess as all-lowercase." ), Suggestion::ReversedWordsArentMuchHarderToGuess => { write!(f, "Reversed words aren't much harder to guess.") } Suggestion::PredictableSubstitutionsDontHelpVeryMuch => write!( f, "Predictable substitutions like '@' instead of 'a' don't help very much." ), Suggestion::UseALongerKeyboardPatternWithMoreTurns => { write!(f, "Use a longer keyboard pattern with more turns.") } Suggestion::AvoidRepeatedWordsAndCharacters => { write!(f, "Avoid repeated words and characters.") } Suggestion::AvoidSequences => write!(f, "Avoid sequences."), Suggestion::AvoidRecentYears => write!(f, "Avoid recent years."), Suggestion::AvoidYearsThatAreAssociatedWithYou => { write!(f, "Avoid years that are associated with you.") } Suggestion::AvoidDatesAndYearsThatAreAssociatedWithYou => { write!(f, "Avoid dates and years that are associated with you.") } } } } #[pymethods] impl Suggestion { fn __str__(&self) -> PyResult { return Ok(format!("{self}")); } } fn match_suggestion(suggestion: zxcvbn::feedback::Suggestion) -> Suggestion { match suggestion { zxcvbn::feedback::Suggestion::UseAFewWordsAvoidCommonPhrases => { Suggestion::UseAFewWordsAvoidCommonPhrases } zxcvbn::feedback::Suggestion::NoNeedForSymbolsDigitsOrUppercaseLetters => { Suggestion::NoNeedForSymbolsDigitsOrUppercaseLetters } zxcvbn::feedback::Suggestion::AddAnotherWordOrTwo => Suggestion::AddAnotherWordOrTwo, zxcvbn::feedback::Suggestion::CapitalizationDoesntHelpVeryMuch => { Suggestion::CapitalizationDoesntHelpVeryMuch } zxcvbn::feedback::Suggestion::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase => { Suggestion::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase } zxcvbn::feedback::Suggestion::ReversedWordsArentMuchHarderToGuess => { Suggestion::ReversedWordsArentMuchHarderToGuess } zxcvbn::feedback::Suggestion::PredictableSubstitutionsDontHelpVeryMuch => { Suggestion::PredictableSubstitutionsDontHelpVeryMuch } zxcvbn::feedback::Suggestion::UseALongerKeyboardPatternWithMoreTurns => { Suggestion::UseALongerKeyboardPatternWithMoreTurns } zxcvbn::feedback::Suggestion::AvoidRepeatedWordsAndCharacters => { Suggestion::AvoidRepeatedWordsAndCharacters } zxcvbn::feedback::Suggestion::AvoidSequences => Suggestion::AvoidSequences, zxcvbn::feedback::Suggestion::AvoidRecentYears => Suggestion::AvoidRecentYears, zxcvbn::feedback::Suggestion::AvoidYearsThatAreAssociatedWithYou => { Suggestion::AvoidYearsThatAreAssociatedWithYou } zxcvbn::feedback::Suggestion::AvoidDatesAndYearsThatAreAssociatedWithYou => { Suggestion::AvoidDatesAndYearsThatAreAssociatedWithYou } } } #[pyclass] #[pyo3(module = "zxcvbn_rs_py")] #[derive(Clone)] struct Feedback { #[pyo3(get)] warning: Option, #[pyo3(get)] suggestions: Vec, } #[pyclass] #[pyo3(module = "zxcvbn_rs_py")] #[derive(Clone)] struct CrackTimesSeconds { #[pyo3(get)] offline_fast_hashing_1e10_per_second: f64, #[pyo3(get)] offline_slow_hashing_1e4_per_second: f64, #[pyo3(get)] online_no_throttling_10_per_second: f64, #[pyo3(get)] online_throttling_100_per_hour: f64, } #[pyclass] #[pyo3(module = "zxcvbn_rs_py")] #[derive(Clone)] struct CrackTimesDisplay { #[pyo3(get)] offline_fast_hashing_1e10_per_second: String, #[pyo3(get)] offline_slow_hashing_1e4_per_second: String, #[pyo3(get)] online_no_throttling_10_per_second: String, #[pyo3(get)] online_throttling_100_per_hour: String, } fn crack_time_seconds_to_float(crack_time: zxcvbn::time_estimates::CrackTimeSeconds) -> f64 { return match crack_time { zxcvbn::time_estimates::CrackTimeSeconds::Integer(i) => i as f64, zxcvbn::time_estimates::CrackTimeSeconds::Float(f) => f, }; } #[pyclass] #[pyo3(module = "zxcvbn_rs_py")] struct Entropy { /// Estimated guesses needed to crack the password #[pyo3(get)] guesses: u64, /// Order of magnitude of `guesses` #[pyo3(get)] guesses_log10: f64, /// List of back-of-the-envelope crack time estimations based on a few scenarios. #[pyo3(get)] crack_times_seconds: CrackTimesSeconds, /// Same as crack_times_seconds, with friendlier display string values. #[pyo3(get)] crack_times_display: CrackTimesDisplay, /// Overall strength score from 0-4. /// Any score less than 3 should be considered too weak. #[pyo3(get)] score: u8, /// Verbal feedback to help choose better passwords. Set when `score` <= 2. #[pyo3(get)] feedback: Option, /// The list of patterns the guess calculation was based on // sequence: Vec, /// How long it took to calculate the answer. #[pyo3(get)] calc_time: u128, } #[pyfunction] #[pyo3(name = "zxcvbn")] fn zxcvbn_rs_py_fn(password: &str, user_inputs: Option>) -> PyResult { let estimate = zxcvbn::zxcvbn(password, user_inputs.unwrap_or(vec![]).as_slice()); return match estimate { Err(_err @ zxcvbn::ZxcvbnError::BlankPassword) => { Err(PyValueError::new_err("Cannot evaluate a blank password")) } Err(_err @ zxcvbn::ZxcvbnError::DurationOutOfRange) => Err(PyRuntimeError::new_err( "Calculation time created a duration out of range", )), Ok(estimate) => { let feedback: Option = match estimate.feedback() { None => None, Some(f) => Some(Feedback { warning: match f.warning() { None => None, Some(w) => Some(match_warning(w)), }, suggestions: f .suggestions() .iter() .map(|s| match_suggestion(*s)) .collect::>() .to_vec(), }), }; let crack_times = estimate.crack_times(); let online_throttling_100_per_hour = crack_times.online_throttling_100_per_hour(); let online_no_throttling_10_per_second = crack_times.online_no_throttling_10_per_second(); let offline_slow_hashing_1e4_per_second = crack_times.offline_slow_hashing_1e4_per_second(); let offline_fast_hashing_1e10_per_second = crack_times.offline_fast_hashing_1e10_per_second(); return Ok(Entropy { guesses: estimate.guesses(), guesses_log10: estimate.guesses_log10(), crack_times_seconds: CrackTimesSeconds { online_throttling_100_per_hour: crack_time_seconds_to_float( online_throttling_100_per_hour, ), online_no_throttling_10_per_second: crack_time_seconds_to_float( online_no_throttling_10_per_second, ), offline_slow_hashing_1e4_per_second: crack_time_seconds_to_float( offline_slow_hashing_1e4_per_second, ), offline_fast_hashing_1e10_per_second: crack_time_seconds_to_float( offline_fast_hashing_1e10_per_second, ), }, crack_times_display: CrackTimesDisplay { online_throttling_100_per_hour: format!("{online_throttling_100_per_hour}"), online_no_throttling_10_per_second: format!( "{online_no_throttling_10_per_second}" ), offline_slow_hashing_1e4_per_second: format!( "{offline_slow_hashing_1e4_per_second}" ), offline_fast_hashing_1e10_per_second: format!( "{offline_fast_hashing_1e10_per_second}" ), }, score: estimate.score(), feedback: feedback, calc_time: estimate.calculation_time().as_millis(), }); } }; } #[pymodule] #[pyo3(name = "zxcvbn_rs_py")] fn zxcvbn_rs_py_module(_py: Python, m: &PyModule) -> PyResult<()> { m.add("__version__", env!("CARGO_PKG_VERSION"))?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_function(wrap_pyfunction!(zxcvbn_rs_py_fn, m)?)?; Ok(()) } zxcvbn-rs-py-0.1.1/zxcvbn_rs_py/000077500000000000000000000000001456636203600166345ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/zxcvbn_rs_py/__init__.py000066400000000000000000000005031456636203600207430ustar00rootroot00000000000000from .zxcvbn_rs_py import ( CrackTimesDisplay, CrackTimesSeconds, Entropy, Feedback, Suggestion, Warning, __version__, zxcvbn, ) __all__ = [ "CrackTimesDisplay", "CrackTimesSeconds", "Entropy", "Feedback", "Suggestion", "Warning", "__version__", "zxcvbn", ] zxcvbn-rs-py-0.1.1/zxcvbn_rs_py/py.typed000066400000000000000000000000001456636203600203210ustar00rootroot00000000000000zxcvbn-rs-py-0.1.1/zxcvbn_rs_py/zxcvbn_rs_py.pyi000066400000000000000000000055561456636203600221200ustar00rootroot00000000000000from enum import Enum, auto __version__: str class Warning(Enum): StraightRowsOfKeysAreEasyToGuess = auto() ShortKeyboardPatternsAreEasyToGuess = auto() RepeatsLikeAaaAreEasyToGuess = auto() RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess = auto() ThisIsATop10Password = auto() ThisIsATop100Password = auto() ThisIsACommonPassword = auto() ThisIsSimilarToACommonlyUsedPassword = auto() SequencesLikeAbcAreEasyToGuess = auto() RecentYearsAreEasyToGuess = auto() AWordByItselfIsEasyToGuess = auto() DatesAreOftenEasyToGuess = auto() NamesAndSurnamesByThemselvesAreEasyToGuess = auto() CommonNamesAndSurnamesAreEasyToGuess = auto() class Suggestion(Enum): UseAFewWordsAvoidCommonPhrases = auto() NoNeedForSymbolsDigitsOrUppercaseLetters = auto() AddAnotherWordOrTwo = auto() CapitalizationDoesntHelpVeryMuch = auto() AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase = auto() ReversedWordsArentMuchHarderToGuess = auto() PredictableSubstitutionsDontHelpVeryMuch = auto() UseALongerKeyboardPatternWithMoreTurns = auto() AvoidRepeatedWordsAndCharacters = auto() AvoidSequences = auto() AvoidRecentYears = auto() AvoidYearsThatAreAssociatedWithYou = auto() AvoidDatesAndYearsThatAreAssociatedWithYou = auto() class Feedback: warning: Warning | None suggestions: list[Suggestion] class CrackTimesSeconds: offline_fast_hashing_1e10_per_second: float offline_slow_hashing_1e4_per_second: float online_no_throttling_10_per_second: float online_throttling_100_per_hour: float class CrackTimesDisplay: offline_fast_hashing_1e10_per_second: str offline_slow_hashing_1e4_per_second: str online_no_throttling_10_per_second: str online_throttling_100_per_hour: str class Entropy: """Result of a password strength check.""" guesses: int """Estimated guesses needed to crack the password""" guesses_log10: float """Order of magnitude of `guesses`.""" crack_times_seconds: CrackTimesSeconds """List of back-of-the-envelope crack time estimations based on a few scenarios.""" crack_times_display: CrackTimesDisplay """Same as crack_times_seconds, with friendlier display string values.""" score: int """ Overall strength score from 0-4. Any score less than 3 should be considered too weak. """ feedback: Feedback | None """Verbal feedback to help choose better passwords. Set when `score` <= 2.""" calc_time: int """How long it took to calculate the answer.""" def zxcvbn(password: str, user_inputs: list[str] | None = None) -> Entropy: """ Measure the strength of a password. Args: password: The password to check. user_inputs: Optional list of strings input by the user in other fields to match against the password. Returns: An `Entropy` object. """ ...