Initial
This commit is contained in:
commit
dd0b48a459
133
.github/CODE_OF_CONDUCT.md
vendored
Normal file
133
.github/CODE_OF_CONDUCT.md
vendored
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||||
|
identity and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the overall
|
||||||
|
community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||||
|
any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email address,
|
||||||
|
without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
<mailto:hs@ox.cx>.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series of
|
||||||
|
actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or permanent
|
||||||
|
ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||||
|
community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.1, available at
|
||||||
|
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by
|
||||||
|
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||||
|
[https://www.contributor-covenant.org/translations][translations].
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||||
|
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||||
|
[FAQ]: https://www.contributor-covenant.org/faq
|
||||||
|
[translations]: https://www.contributor-covenant.org/translations
|
||||||
178
.github/CONTRIBUTING.md
vendored
Normal file
178
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
# How To Contribute
|
||||||
|
|
||||||
|
First off, thank you for considering contributing to *argon2-cffi-bindings*!
|
||||||
|
It's people like *you* who make it such a great tool for everyone.
|
||||||
|
|
||||||
|
This document intends to make contribution more accessible by codifying tribal knowledge and expectations.
|
||||||
|
Don't be afraid to open half-finished PRs, and ask questions if something is unclear!
|
||||||
|
|
||||||
|
Please note that this project is released with a Contributor [Code of Conduct](https://github.com/hynek/argon2-cffi-bindings/blob/main/.github/CODE_OF_CONDUCT.md).
|
||||||
|
By participating in this project you agree to abide by its terms.
|
||||||
|
Please report any harm to [Hynek Schlawack] in any way you find appropriate.
|
||||||
|
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
- No contribution is too small!
|
||||||
|
Please submit as many fixes for typos and grammar bloopers as you can!
|
||||||
|
- Try to limit each pull request to *one* change only.
|
||||||
|
- Since we squash on merge, it's up to you how you handle updates to the main branch.
|
||||||
|
Whether you prefer to rebase on main or merge main into your branch, do whatever is more comfortable for you.
|
||||||
|
- *Always* add tests and docs for your code.
|
||||||
|
This is a hard rule; patches with missing tests or documentation can't be merged.
|
||||||
|
- Make sure your changes pass our [CI].
|
||||||
|
You won't get any feedback until it's green unless you ask for it.
|
||||||
|
- Once you've addressed review feedback, make sure to bump the pull request with a short note, so we know you're done.
|
||||||
|
- Don’t break backwards compatibility.
|
||||||
|
|
||||||
|
|
||||||
|
## Local Development Environment
|
||||||
|
|
||||||
|
You can (and should) run our test suite using [*tox*].
|
||||||
|
However, you’ll probably want a more traditional environment as well.
|
||||||
|
We highly recommend to develop using the latest Python release because we try to take advantage of modern features whenever possible.
|
||||||
|
|
||||||
|
First create a [virtual environment](https://virtualenv.pypa.io/) so you don't break your system-wide Python installation.
|
||||||
|
It’s out of scope for this document to list all the ways to manage virtual environments in Python, but if you don’t already have a pet way, take some time to look at tools like [*direnv*](https://hynek.me/til/python-project-local-venvs/), [*virtualfish*](https://virtualfish.readthedocs.io/), and [*virtualenvwrapper*](https://virtualenvwrapper.readthedocs.io/).
|
||||||
|
|
||||||
|
Next, get an up to date checkout of the *argon2-cffi-bindings* repository:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ git clone git@github.com:hynek/argon2-cffi-bindings.git
|
||||||
|
```
|
||||||
|
|
||||||
|
or if you want to use git via `https`:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ git clone https://github.com/hynek/argon2-cffi-bindings.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Change into the newly created directory and **activate your virtual environment**
|
||||||
|
|
||||||
|
First you have to make sure that our *Argon2* *git* submodule is up-to-date:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ cd argon2-cffi-bindings
|
||||||
|
$ git submodule init # initialize git submodule mechanics
|
||||||
|
$ git submodule update # update the vendored Argon2 C library to the version we are packaging
|
||||||
|
```
|
||||||
|
|
||||||
|
Now an editable version of *argon2-cffi-bindings* along with its test requirements can be installed as usual:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ python -m pip install --upgrade pip setuptools cffi # PLEASE don't skip this step
|
||||||
|
$ python setup.py build # build the vendored C code
|
||||||
|
$ python -m pip install -e '.[dev]'
|
||||||
|
```
|
||||||
|
|
||||||
|
At this point,
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ python -m pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
should work and pass.
|
||||||
|
|
||||||
|
To avoid committing code that violates our style guide, we strongly advise you to install [*pre-commit*] [^dev] hooks:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pre-commit install
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also run them anytime (as our tox does) using:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pre-commit run --all-files
|
||||||
|
```
|
||||||
|
|
||||||
|
[^dev]: *pre-commit* should have been installed into your virtualenv automatically when you ran `pip install -e '.[dev]'` above.
|
||||||
|
If *pre-commit* is missing, your probably need to run `pip install -e '.[dev]'` again.
|
||||||
|
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
- Obey [PEP 8](https://www.python.org/dev/peps/pep-0008/) and [PEP 257](https://www.python.org/dev/peps/pep-0257/).
|
||||||
|
We use the `"""`-on-separate-lines style for docstrings:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def func(x):
|
||||||
|
"""
|
||||||
|
Do something.
|
||||||
|
|
||||||
|
:param str x: A very important parameter.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
- If you add or change public APIs, tag the docstring using `.. versionadded:: 16.0.0 WHAT` or `.. versionchanged:: 16.2.0 WHAT`.
|
||||||
|
- We use [*isort*](https://github.com/PyCQA/isort) to sort our imports, and we use [*Black*](https://github.com/psf/black) with line length of 79 characters to format our code.
|
||||||
|
As long as you run our full [*tox*] suite before committing, or install our [*pre-commit*] hooks (ideally you'll do both – see [*Local Development Environment*](#local-development-environment) below), you won't have to spend any time on formatting your code at all.
|
||||||
|
If you don't, [CI] will catch it for you – but that seems like a waste of your time!
|
||||||
|
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
- Write your asserts as `expected == actual` to line them up nicely:
|
||||||
|
|
||||||
|
```python
|
||||||
|
x = f()
|
||||||
|
|
||||||
|
assert 42 == x.some_attribute
|
||||||
|
assert "foo" == x._a_private_attribute
|
||||||
|
```
|
||||||
|
|
||||||
|
- To run the test suite, all you need is a recent [*tox*].
|
||||||
|
It will ensure the test suite runs with all dependencies against all Python versions just as it will in our [CI].
|
||||||
|
If you lack some Python versions, you can can always limit the environments like `tox -e py38,py39`, or make it a non-failure using `tox --skip-missing-interpreters`.
|
||||||
|
|
||||||
|
In that case you should look into [*asdf*](https://asdf-vm.com) or [*pyenv*](https://github.com/pyenv/pyenv), which make it very easy to install many different Python versions in parallel.
|
||||||
|
- Write [good test docstrings](https://jml.io/pages/test-docstrings.html).
|
||||||
|
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- Use [semantic newlines] in [Markdown*] files (files ending in `.md`):
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
This is a sentence.
|
||||||
|
This is another sentence.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Changelog
|
||||||
|
|
||||||
|
If your change is noteworthy, there needs to be a changelog entry in `CHANGELOG.md`.
|
||||||
|
|
||||||
|
- As with other docs, please use [semantic newlines] in the changelog.
|
||||||
|
- Wrap symbols like modules, functions, or classes into backticks so they are rendered in a `monospace font`.
|
||||||
|
- Wrap arguments into asterisks like in docstrings:
|
||||||
|
`Added new argument *an_argument*.`
|
||||||
|
- If you mention functions or other callables, add parentheses at the end of their names:
|
||||||
|
`_argon2_cffi_bindings.func()` or `_argon2_cffi_bindings.Class.method()`.
|
||||||
|
This makes the changelog a lot more readable.
|
||||||
|
- Prefer simple past tense or constructions with "now".
|
||||||
|
For example:
|
||||||
|
|
||||||
|
+ Added `_argon2_cffi_bindings.func()`.
|
||||||
|
+ `_argon2_cffi_bindings.func()` now doesn't crash the Large Hadron Collider anymore when passed the *foobar* argument.
|
||||||
|
|
||||||
|
Example entries:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Added `_argon2_cffi_bindings.func()`.
|
||||||
|
The feature really *is* awesome.
|
||||||
|
```
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
`_argon2_cffi_bindings.func()` now doesn't crash the Large Hadron Collider anymore when passed the *foobar* argument.
|
||||||
|
The bug really *was* nasty.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
[CI]: https://github.com/hynek/argon2-cffi-bindings/actions
|
||||||
|
[Hynek Schlawack]: https://hynek.me/about/
|
||||||
|
[*pre-commit*]: https://pre-commit.com/
|
||||||
|
[*tox*]: https://https://tox.wiki/
|
||||||
|
[semantic newlines]: https://rhodesmill.org/brandon/2012/one-sentence-per-line/
|
||||||
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
github: hynek
|
||||||
|
ko_fi: the_hynek
|
||||||
104
.github/workflows/main.yml
vendored
Normal file
104
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
---
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
pull_request:
|
||||||
|
branches: ["main"]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORCE_COLOR: "1" # Make tools pretty.
|
||||||
|
TOX_TESTENV_PASSENV: "FORCE_COLOR"
|
||||||
|
PYTHON_LATEST: "3.10"
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
name: "tox on ${{ matrix.python-version }}"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy-3.7"]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: "actions/checkout@v2"
|
||||||
|
with:
|
||||||
|
submodules: "recursive"
|
||||||
|
- uses: "actions/setup-python@v2"
|
||||||
|
with:
|
||||||
|
python-version: "${{ matrix.python-version }}"
|
||||||
|
- name: "Install dependencies"
|
||||||
|
run: |
|
||||||
|
python -VV
|
||||||
|
python -m site
|
||||||
|
python -m pip install --upgrade pip setuptools wheel
|
||||||
|
python -m pip install --upgrade virtualenv tox tox-gh-actions
|
||||||
|
|
||||||
|
- name: "Run tox targets for ${{ matrix.python-version }}"
|
||||||
|
run: "python -m tox"
|
||||||
|
|
||||||
|
|
||||||
|
system-package:
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
name: "Install and test with system package of Argon2."
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: "actions/checkout@v2"
|
||||||
|
- uses: "actions/setup-python@v2"
|
||||||
|
with:
|
||||||
|
python-version: ${{env.PYTHON_LATEST}}
|
||||||
|
- name: "Install dependencies"
|
||||||
|
run: |
|
||||||
|
sudo apt-get install libargon2-0 libargon2-0-dev
|
||||||
|
# Ensure we cannot use our own Argon2 by accident.
|
||||||
|
rm -rf extras
|
||||||
|
python -VV
|
||||||
|
python -m site
|
||||||
|
python -m pip install --upgrade pip setuptools wheel
|
||||||
|
python -m pip install --upgrade virtualenv tox
|
||||||
|
|
||||||
|
- run: "python -m tox -e system-argon2"
|
||||||
|
|
||||||
|
|
||||||
|
package:
|
||||||
|
name: "Build & verify package"
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: "actions/checkout@v2"
|
||||||
|
with:
|
||||||
|
submodules: "recursive"
|
||||||
|
- uses: "actions/setup-python@v2"
|
||||||
|
with:
|
||||||
|
python-version: ${{env.PYTHON_LATEST}}
|
||||||
|
|
||||||
|
- run: "python -m pip install build twine check-wheel-contents"
|
||||||
|
- run: "python -m build --sdist --wheel ."
|
||||||
|
- run: "ls -l dist"
|
||||||
|
- run: "check-wheel-contents dist/*.whl"
|
||||||
|
- name: "Check long_description"
|
||||||
|
run: "python -m twine check dist/*"
|
||||||
|
|
||||||
|
|
||||||
|
install-dev:
|
||||||
|
name: "Verify dev env"
|
||||||
|
runs-on: "${{ matrix.os }}"
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: "actions/checkout@v2"
|
||||||
|
with:
|
||||||
|
submodules: "recursive"
|
||||||
|
- uses: "actions/setup-python@v2"
|
||||||
|
with:
|
||||||
|
python-version: ${{env.PYTHON_LATEST}}
|
||||||
|
- run: python -m pip install --upgrade pip
|
||||||
|
- run: python setup.py build
|
||||||
|
- run: python -m pip install -e .[dev]
|
||||||
|
- name: "Import package"
|
||||||
|
run: "python -c 'from _argon2_cffi_bindings import ffi, lib; print(lib.ARGON2_VERSION_NUMBER)'"
|
||||||
45
.github/workflows/wheels.yml
vendored
Normal file
45
.github/workflows/wheels.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
name: Build Wheels
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
wheels:
|
||||||
|
name: Building for ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: "recursive"
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
with:
|
||||||
|
platforms: arm64
|
||||||
|
|
||||||
|
- uses: pypa/cibuildwheel@v2.3.0
|
||||||
|
env:
|
||||||
|
# Only build CPython 3.6, because we have portable abi3 wheels.
|
||||||
|
# Windows arm64 is only available on 3.9 and later.
|
||||||
|
CIBW_BUILD: "cp36-* pp37-* pp38-* cp39-win_arm64"
|
||||||
|
CIBW_ARCHS_LINUX: "auto aarch64"
|
||||||
|
CIBW_ARCHS_MACOS: "auto"
|
||||||
|
|
||||||
|
# Unfortunately, Argon2 currently doesn't compile on Apple Silicon.
|
||||||
|
# CIBW_ARCHS_MACOS: auto universal2
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
path: wheelhouse/*.whl
|
||||||
|
|
||||||
|
...
|
||||||
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.tox
|
||||||
|
*.egg-info
|
||||||
|
*.so
|
||||||
|
build
|
||||||
|
dist
|
||||||
|
__pycache__
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "libargon2"]
|
||||||
|
path = extras/libargon2
|
||||||
|
url = https://github.com/P-H-C/phc-winner-argon2.git
|
||||||
30
.pre-commit-config.yaml
Normal file
30
.pre-commit-config.yaml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
ci:
|
||||||
|
autoupdate_schedule: monthly
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 21.11b1
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
language_version: python3.10
|
||||||
|
|
||||||
|
- repo: https://github.com/PyCQA/isort
|
||||||
|
rev: 5.10.1
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
additional_dependencies: [toml]
|
||||||
|
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: 4.0.1
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
language_version: python3.10
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.0.1
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: debug-statements
|
||||||
|
- id: check-toml
|
||||||
12
CHANGELOG.md
Normal file
12
CHANGELOG.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Calendar Versioning](https://calver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Initial import from [*argon2-cffi*](https://github.com/hynek/argon2-cffi).
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2021 Hynek Schlawack
|
||||||
|
|
||||||
|
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.
|
||||||
6
MANIFEST.in
Normal file
6
MANIFEST.in
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
include *.md *.txt *.ini LICENSE .pre-commit-config.yaml pyproject.toml
|
||||||
|
exclude src/argon2/_ffi.py .gitmodules extras/libargon2/.git *.yml
|
||||||
|
graft tests
|
||||||
|
graft .github
|
||||||
|
recursive-exclude tests *.pyc
|
||||||
|
graft extras
|
||||||
84
README.md
Normal file
84
README.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# Python CFFI Bindings for Argon2
|
||||||
|
|
||||||
|
*argon2-cffi-bindings* provides low-level [*CFFI*](https://cffi.readthedocs.io/) bindings to the [*Argon2*] password hashing algorithm including a vendored version of them.
|
||||||
|
|
||||||
|
<!-- Extract commit ID; refresh using `tox -e cog`
|
||||||
|
[[[cog
|
||||||
|
import subprocess
|
||||||
|
cp = subprocess.run(["git", "submodule"], capture_output=True)
|
||||||
|
id = cp.stdout[1:].decode().split(" ", 1)[0]
|
||||||
|
link = f'[**`{id[:7]}`**](https://github.com/P-H-C/phc-winner-argon2/commit/{id})'
|
||||||
|
print(f"The currently vendored *Argon2* commit ID is {link}.")
|
||||||
|
]]] -->
|
||||||
|
The currently vendored *Argon2* commit ID is [**`f57e61e`**](https://github.com/P-H-C/phc-winner-argon2/commit/f57e61e19229e23c4445b85494dbf7c07de721cb).
|
||||||
|
<!-- [[[end]]] -->
|
||||||
|
|
||||||
|
> If you want to hash passwords in an application, this package is **not** for you.
|
||||||
|
> Have a look at [*argon2-cffi*] with its high-level abstractions!
|
||||||
|
|
||||||
|
These bindings have been extracted from [*argon2-cffi*] and it remains its main consumer.
|
||||||
|
However, they may be used by other packages that want to use *Argon2* library without dealing with C-related complexities.
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The provided *CFFI* bindings are compiled in API mode.
|
||||||
|
Best effort is given to provide binary wheels for as many platforms as possible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
A copy of [*Argon2*] is vendored and used by default, but can be disabled if *argon2-cffi-bindings* is installed using:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ env ARGON2_CFFI_USE_SYSTEM=1 \
|
||||||
|
python -m pip install --no-binary=argon2-cffi-bindings argon2-cffi-bindings
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Python API
|
||||||
|
|
||||||
|
Since this package is intended to be an implementation detail, it uses a private module name.
|
||||||
|
Therefore you have to import the symbols from `_argon2_cffi_bindings`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from _argon2_cffi_bindings import ffi, lib
|
||||||
|
```
|
||||||
|
|
||||||
|
Please refer to [*cffi* documentation](https://cffi.readthedocs.io/en/latest/using.html) on how to use the `ffi` and `lib` objects.
|
||||||
|
|
||||||
|
The list of symbols that are provided can be found in the [`_ffi_build.py` file](https://github.com/hynek/argon2-cffi-bindings/blob/main/src/_argon2_cffi_bindings/_ffi_build.py).
|
||||||
|
|
||||||
|
[*Argon2*]: https://github.com/p-h-c/phc-winner-argon2
|
||||||
|
[*argon2-cffi*]: https://argon2-cffi.readthedocs.io/
|
||||||
|
|
||||||
|
|
||||||
|
## Project Information
|
||||||
|
|
||||||
|
*argon2-cffi-bindings* is available under the MIT license, available from [PyPI](https://pypi.org/project/argon2-cffi-bindings/), the source code and documentation can be found on [GitHub](https://github.com/hynek/argon2-cffi-bindings).
|
||||||
|
|
||||||
|
*argon2-cffi-bindings* targets Python 3.6 and later, including PyPy3.
|
||||||
|
|
||||||
|
|
||||||
|
### Credits & License
|
||||||
|
|
||||||
|
*argon2-cffi-bindings* is written and maintained by [Hynek Schlawack](https://hynek.me/about/).
|
||||||
|
It is released under the [MIT license](https://github.com/hynek/argon2-cffi/blob/main/LICENSE>).
|
||||||
|
|
||||||
|
The development is kindly supported by [Variomedia AG](https://www.variomedia.de/).
|
||||||
|
|
||||||
|
The authors of *Argon2* were very helpful to get the library to compile on ancient versions of Visual Studio for ancient versions of Python.
|
||||||
|
|
||||||
|
The documentation quotes frequently in verbatim from the *Argon2* [paper](https://www.password-hashing.net/argon2-specs.pdf) to avoid mistakes by rephrasing.
|
||||||
|
|
||||||
|
|
||||||
|
#### Vendored Code
|
||||||
|
|
||||||
|
The original *Argon2* repo can be found at <https://github.com/P-H-C/phc-winner-argon2/>.
|
||||||
|
|
||||||
|
Except for the components listed below, the *Argon2* code in this repository is copyright (c) 2015 Daniel Dinu, Dmitry Khovratovich (main authors), Jean-Philippe Aumasson and Samuel Neves, and under [CC0] license.
|
||||||
|
|
||||||
|
The string encoding routines in src/encoding.c are copyright (c) 2015 Thomas Pornin, and under [CC0] license.
|
||||||
|
|
||||||
|
The [*BLAKE2*](https://www.blake2.net) code in ``src/blake2/`` is copyright (c) Samuel Neves, 2013-2015, and under [CC0] license.
|
||||||
|
|
||||||
|
[CC0]: https://creativecommons.org/publicdomain/zero/1.0/
|
||||||
1
extras/libargon2
Submodule
1
extras/libargon2
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit f57e61e19229e23c4445b85494dbf7c07de721cb
|
||||||
22
pyproject.toml
Normal file
22
pyproject.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=45", "setuptools_scm>=6.2", "wheel", "cffi>=1.0"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
|
||||||
|
[tool.setuptools_scm]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
addopts = "-ra --strict-markers --capture=no"
|
||||||
|
xfail_strict = true
|
||||||
|
testpaths = "tests"
|
||||||
|
filterwarnings = [
|
||||||
|
"once::Warning",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 79
|
||||||
|
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
profile = "attrs"
|
||||||
357
setup.py
Normal file
357
setup.py
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from distutils.command.build import build
|
||||||
|
from distutils.command.build_clib import build_clib
|
||||||
|
from distutils.errors import DistutilsSetupError
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from setuptools import find_packages, setup
|
||||||
|
from setuptools.command.install import install
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
NAME = "argon2-cffi-bindings"
|
||||||
|
DESCRIPTION = "Low-level CFFI bindings for Argon2"
|
||||||
|
URL = "https://github.com/hynek/argon2-cffi-bindings"
|
||||||
|
PACKAGES = find_packages(where="src")
|
||||||
|
LICENSE = "MIT"
|
||||||
|
AUTHOR = "Hynek Schlawack"
|
||||||
|
EMAIL = "hs@ox.cx"
|
||||||
|
|
||||||
|
|
||||||
|
HERE = Path(__file__).parent.resolve()
|
||||||
|
|
||||||
|
use_sse2 = os.environ.get("ARGON2_CFFI_USE_SSE2", None)
|
||||||
|
if use_sse2 == "1":
|
||||||
|
optimized = True
|
||||||
|
elif use_sse2 == "0":
|
||||||
|
optimized = False
|
||||||
|
else:
|
||||||
|
# Optimized version requires SSE2 extensions. They have been around since
|
||||||
|
# 2001 so we try to compile it on every recent-ish x86.
|
||||||
|
optimized = platform.machine() in ("i686", "x86", "x86_64", "AMD64")
|
||||||
|
|
||||||
|
CFFI_MODULES = ["src/_argon2_cffi_bindings/_ffi_build.py:ffi"]
|
||||||
|
|
||||||
|
lib_base = Path("extras") / "libargon2" / "src"
|
||||||
|
include_dirs = [
|
||||||
|
str(lib_base / path)
|
||||||
|
for path in (
|
||||||
|
Path("..") / "include",
|
||||||
|
"blake2",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
sources = [
|
||||||
|
str(lib_base / path)
|
||||||
|
for path in (
|
||||||
|
"argon2.c",
|
||||||
|
Path("blake2") / "blake2b.c",
|
||||||
|
"core.c",
|
||||||
|
"encoding.c",
|
||||||
|
"opt.c" if optimized else "ref.c",
|
||||||
|
"thread.c",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
# This is the definition of the vendored libargon2.
|
||||||
|
LIBRARIES = [("argon2", {"include_dirs": include_dirs, "sources": sources})]
|
||||||
|
|
||||||
|
windows = "win32" in str(sys.platform).lower()
|
||||||
|
|
||||||
|
META_PATH = HERE / "src" / "_argon2_cffi_bindings" / "__init__.py"
|
||||||
|
KEYWORDS = ["password", "hash", "hashing", "security", "bindings", "cffi"]
|
||||||
|
PROJECT_URLS = {
|
||||||
|
"Source Code": "https://github.com/hynek/argon2-cffi-bindings",
|
||||||
|
"Funding": "https://github.com/sponsors/hynek",
|
||||||
|
"Tidelift": "https://tidelift.com/subscription/pkg/pypi-argon2-cffi?"
|
||||||
|
"utm_source=pypi-argon2-cffi&utm_medium=pypi",
|
||||||
|
"Ko-fi": "https://ko-fi.com/the_hynek",
|
||||||
|
}
|
||||||
|
CLASSIFIERS = [
|
||||||
|
"Development Status :: 5 - Production/Stable",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Natural Language :: English",
|
||||||
|
"Operating System :: MacOS :: MacOS X",
|
||||||
|
"Operating System :: Microsoft :: Windows",
|
||||||
|
"Operating System :: POSIX",
|
||||||
|
"Operating System :: Unix",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.6",
|
||||||
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Topic :: Security :: Cryptography",
|
||||||
|
"Topic :: Security",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
]
|
||||||
|
|
||||||
|
PYTHON_REQUIRES = ">=3.6"
|
||||||
|
SETUP_REQUIRES = ["cffi>=1.0.0", "setuptools_scm>=6.2"]
|
||||||
|
INSTALL_REQUIRES = ["cffi>=1.0.0"]
|
||||||
|
EXTRAS_REQUIRE = {"tests": ["pytest"]}
|
||||||
|
EXTRAS_REQUIRE["dev"] = EXTRAS_REQUIRE["tests"] + [
|
||||||
|
"cogapp",
|
||||||
|
"pre-commit",
|
||||||
|
"wheel",
|
||||||
|
]
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def keywords_with_side_effects(argv):
|
||||||
|
"""
|
||||||
|
Get a dictionary with setup keywords that (can) have side effects.
|
||||||
|
|
||||||
|
:param argv: A list of strings with command line arguments.
|
||||||
|
|
||||||
|
:returns: A dictionary with keyword arguments for the ``setup()`` function.
|
||||||
|
This setup.py script uses the setuptools 'setup_requires' feature
|
||||||
|
because this is required by the cffi package to compile extension
|
||||||
|
modules. The purpose of ``keywords_with_side_effects()`` is to avoid
|
||||||
|
triggering the cffi build process as a result of setup.py invocations
|
||||||
|
that don't need the cffi module to be built (setup.py serves the dual
|
||||||
|
purpose of exposing package metadata).
|
||||||
|
|
||||||
|
Stolen from pyca/cryptography.
|
||||||
|
"""
|
||||||
|
no_setup_requires_arguments = (
|
||||||
|
"-h",
|
||||||
|
"--help",
|
||||||
|
"-n",
|
||||||
|
"--dry-run",
|
||||||
|
"-q",
|
||||||
|
"--quiet",
|
||||||
|
"-v",
|
||||||
|
"--verbose",
|
||||||
|
"-V",
|
||||||
|
"--version",
|
||||||
|
"--author",
|
||||||
|
"--author-email",
|
||||||
|
"--classifiers",
|
||||||
|
"--contact",
|
||||||
|
"--contact-email",
|
||||||
|
"--description",
|
||||||
|
"--egg-base",
|
||||||
|
"--fullname",
|
||||||
|
"--help-commands",
|
||||||
|
"--keywords",
|
||||||
|
"--licence",
|
||||||
|
"--license",
|
||||||
|
"--long-description",
|
||||||
|
"--maintainer",
|
||||||
|
"--maintainer-email",
|
||||||
|
"--name",
|
||||||
|
"--no-user-cfg",
|
||||||
|
"--obsoletes",
|
||||||
|
"--platforms",
|
||||||
|
"--provides",
|
||||||
|
"--requires",
|
||||||
|
"--url",
|
||||||
|
"clean",
|
||||||
|
"egg_info",
|
||||||
|
"register",
|
||||||
|
"sdist",
|
||||||
|
"upload",
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_short_option(argument):
|
||||||
|
"""Check whether a command line argument is a short option."""
|
||||||
|
return len(argument) >= 2 and argument[0] == "-" and argument[1] != "-"
|
||||||
|
|
||||||
|
def expand_short_options(argument):
|
||||||
|
"""Expand combined short options into canonical short options."""
|
||||||
|
return ("-" + char for char in argument[1:])
|
||||||
|
|
||||||
|
def argument_without_setup_requirements(argv, i):
|
||||||
|
"""Check whether a command line argument needs setup requirements."""
|
||||||
|
if argv[i] in no_setup_requires_arguments:
|
||||||
|
# Simple case: An argument which is either an option or a command
|
||||||
|
# which doesn't need setup requirements.
|
||||||
|
return True
|
||||||
|
elif is_short_option(argv[i]) and all(
|
||||||
|
option in no_setup_requires_arguments
|
||||||
|
for option in expand_short_options(argv[i])
|
||||||
|
):
|
||||||
|
# Not so simple case: Combined short options none of which need
|
||||||
|
# setup requirements.
|
||||||
|
return True
|
||||||
|
elif argv[i - 1 : i] == ["--egg-base"]:
|
||||||
|
# Tricky case: --egg-info takes an argument which should not make
|
||||||
|
# us use setup_requires (defeating the purpose of this code).
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if all(
|
||||||
|
argument_without_setup_requirements(argv, i)
|
||||||
|
for i in range(1, len(argv))
|
||||||
|
):
|
||||||
|
return {"cmdclass": {"build": DummyBuild, "install": DummyInstall}}
|
||||||
|
else:
|
||||||
|
global LIBRARIES
|
||||||
|
use_system_argon2 = (
|
||||||
|
os.environ.get("ARGON2_CFFI_USE_SYSTEM", "0") == "1"
|
||||||
|
)
|
||||||
|
if use_system_argon2:
|
||||||
|
disable_subcommand(build, "build_clib")
|
||||||
|
LIBRARIES = []
|
||||||
|
cmdclass = {"build_clib": BuildCLibWithCompilerFlags}
|
||||||
|
if BDistWheel is not None:
|
||||||
|
cmdclass["bdist_wheel"] = BDistWheel
|
||||||
|
return {
|
||||||
|
"setup_requires": SETUP_REQUIRES,
|
||||||
|
"cffi_modules": CFFI_MODULES,
|
||||||
|
"libraries": LIBRARIES,
|
||||||
|
"cmdclass": cmdclass,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def disable_subcommand(command, subcommand_name):
|
||||||
|
for name, method in command.sub_commands:
|
||||||
|
if name == subcommand_name:
|
||||||
|
command.sub_commands.remove((subcommand_name, method))
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
setup_requires_error = (
|
||||||
|
"Requested setup command that needs 'setup_requires' while command line "
|
||||||
|
"arguments implied a side effect free command or option."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DummyBuild(build):
|
||||||
|
"""
|
||||||
|
This class makes it very obvious when ``keywords_with_side_effects()`` has
|
||||||
|
incorrectly interpreted the command line arguments to ``setup.py build`` as
|
||||||
|
one of the 'side effect free' commands or options.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
raise RuntimeError(setup_requires_error)
|
||||||
|
|
||||||
|
|
||||||
|
class DummyInstall(install):
|
||||||
|
"""
|
||||||
|
This class makes it very obvious when ``keywords_with_side_effects()`` has
|
||||||
|
incorrectly interpreted the command line arguments to ``setup.py install``
|
||||||
|
as one of the 'side effect free' commands or options.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
raise RuntimeError(setup_requires_error)
|
||||||
|
|
||||||
|
|
||||||
|
META_FILE = META_PATH.read_text()
|
||||||
|
|
||||||
|
|
||||||
|
def find_meta(meta):
|
||||||
|
"""
|
||||||
|
Extract __*meta*__ from META_FILE.
|
||||||
|
"""
|
||||||
|
meta_match = re.search(
|
||||||
|
fr"^__{meta}__ = ['\"]([^'\"]*)['\"]", META_FILE, re.M
|
||||||
|
)
|
||||||
|
if meta_match:
|
||||||
|
return meta_match.group(1)
|
||||||
|
raise RuntimeError(f"Unable to find __{meta}__ string.")
|
||||||
|
|
||||||
|
|
||||||
|
LONG = (HERE / "README.md").read_text()
|
||||||
|
|
||||||
|
|
||||||
|
class BuildCLibWithCompilerFlags(build_clib):
|
||||||
|
"""
|
||||||
|
We need to pass ``-msse2`` for the optimized build.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def build_libraries(self, libraries):
|
||||||
|
"""
|
||||||
|
Mostly copy pasta from ``distutils.command.build_clib``.
|
||||||
|
"""
|
||||||
|
for (lib_name, build_info) in libraries:
|
||||||
|
sources = build_info.get("sources")
|
||||||
|
if sources is None or not isinstance(sources, (list, tuple)):
|
||||||
|
raise DistutilsSetupError(
|
||||||
|
"in 'libraries' option (library '%s'), "
|
||||||
|
"'sources' must be present and must be "
|
||||||
|
"a list of source filenames" % lib_name
|
||||||
|
)
|
||||||
|
sources = list(sources)
|
||||||
|
|
||||||
|
print(f"building '{lib_name}' library")
|
||||||
|
|
||||||
|
# First, compile the source code to object files in the library
|
||||||
|
# directory. (This should probably change to putting object
|
||||||
|
# files in a temporary build directory.)
|
||||||
|
macros = build_info.get("macros")
|
||||||
|
include_dirs = build_info.get("include_dirs")
|
||||||
|
objects = self.compiler.compile(
|
||||||
|
sources,
|
||||||
|
extra_preargs=["-msse2"] if optimized and not windows else [],
|
||||||
|
output_dir=self.build_temp,
|
||||||
|
macros=macros,
|
||||||
|
include_dirs=include_dirs,
|
||||||
|
debug=self.debug,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Now "link" the object files together into a static library.
|
||||||
|
# (On Unix at least, this isn't really linking -- it just
|
||||||
|
# builds an archive. Whatever.)
|
||||||
|
self.compiler.create_static_lib(
|
||||||
|
objects, lib_name, output_dir=self.build_clib, debug=self.debug
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info > (3,) and platform.python_implementation() == "CPython":
|
||||||
|
try:
|
||||||
|
import wheel.bdist_wheel
|
||||||
|
except ImportError:
|
||||||
|
BDistWheel = None
|
||||||
|
else:
|
||||||
|
|
||||||
|
class BDistWheel(wheel.bdist_wheel.bdist_wheel):
|
||||||
|
def finalize_options(self):
|
||||||
|
self.py_limited_api = f"cp3{sys.version_info[1]}"
|
||||||
|
wheel.bdist_wheel.bdist_wheel.finalize_options(self)
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
BDistWheel = None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
setup(
|
||||||
|
name=NAME,
|
||||||
|
description=DESCRIPTION,
|
||||||
|
license=LICENSE,
|
||||||
|
url=URL,
|
||||||
|
project_urls=PROJECT_URLS,
|
||||||
|
use_scm_version=True, # setuptools_scm
|
||||||
|
author=AUTHOR,
|
||||||
|
author_email=EMAIL,
|
||||||
|
maintainer=AUTHOR,
|
||||||
|
maintainer_email=EMAIL,
|
||||||
|
long_description=LONG,
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
keywords=KEYWORDS,
|
||||||
|
packages=PACKAGES,
|
||||||
|
package_dir={"": "src"},
|
||||||
|
classifiers=CLASSIFIERS,
|
||||||
|
python_requires=PYTHON_REQUIRES,
|
||||||
|
install_requires=INSTALL_REQUIRES,
|
||||||
|
extras_require=EXTRAS_REQUIRE,
|
||||||
|
# CFFI
|
||||||
|
zip_safe=False,
|
||||||
|
ext_package="_argon2_cffi_bindings",
|
||||||
|
**keywords_with_side_effects(sys.argv),
|
||||||
|
)
|
||||||
6
src/_argon2_cffi_bindings/__init__.py
Normal file
6
src/_argon2_cffi_bindings/__init__.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from ._ffi import ffi, lib
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["ffi", "lib"]
|
||||||
177
src/_argon2_cffi_bindings/_ffi_build.py
Normal file
177
src/_argon2_cffi_bindings/_ffi_build.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from cffi import FFI
|
||||||
|
|
||||||
|
|
||||||
|
include_dirs = [os.path.join("extras", "libargon2", "include")]
|
||||||
|
use_system_argon2 = os.environ.get("ARGON2_CFFI_USE_SYSTEM", "0") == "1"
|
||||||
|
if use_system_argon2:
|
||||||
|
include_dirs = []
|
||||||
|
|
||||||
|
|
||||||
|
ffi = FFI()
|
||||||
|
ffi.set_source(
|
||||||
|
"_ffi",
|
||||||
|
"#include <argon2.h>",
|
||||||
|
include_dirs=include_dirs,
|
||||||
|
libraries=["argon2"],
|
||||||
|
)
|
||||||
|
|
||||||
|
ffi.cdef(
|
||||||
|
"""\
|
||||||
|
typedef enum Argon2_type {
|
||||||
|
Argon2_d = ...,
|
||||||
|
Argon2_i = ...,
|
||||||
|
Argon2_id = ...,
|
||||||
|
} argon2_type;
|
||||||
|
typedef enum Argon2_version {
|
||||||
|
ARGON2_VERSION_10 = ...,
|
||||||
|
ARGON2_VERSION_13 = ...,
|
||||||
|
ARGON2_VERSION_NUMBER = ...
|
||||||
|
} argon2_version;
|
||||||
|
|
||||||
|
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
||||||
|
const uint32_t parallelism, const void *pwd,
|
||||||
|
const size_t pwdlen, const void *salt,
|
||||||
|
const size_t saltlen, void *hash,
|
||||||
|
const size_t hashlen, char *encoded,
|
||||||
|
const size_t encodedlen, argon2_type type,
|
||||||
|
const uint32_t version);
|
||||||
|
|
||||||
|
int argon2_verify(const char *encoded, const void *pwd,
|
||||||
|
const size_t pwdlen, argon2_type type);
|
||||||
|
|
||||||
|
const char *argon2_error_message(int error_code);
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
|
||||||
|
typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
|
||||||
|
|
||||||
|
typedef struct Argon2_Context {
|
||||||
|
uint8_t *out; /* output array */
|
||||||
|
uint32_t outlen; /* digest length */
|
||||||
|
|
||||||
|
uint8_t *pwd; /* password array */
|
||||||
|
uint32_t pwdlen; /* password length */
|
||||||
|
|
||||||
|
uint8_t *salt; /* salt array */
|
||||||
|
uint32_t saltlen; /* salt length */
|
||||||
|
|
||||||
|
uint8_t *secret; /* key array */
|
||||||
|
uint32_t secretlen; /* key length */
|
||||||
|
|
||||||
|
uint8_t *ad; /* associated data array */
|
||||||
|
uint32_t adlen; /* associated data length */
|
||||||
|
|
||||||
|
uint32_t t_cost; /* number of passes */
|
||||||
|
uint32_t m_cost; /* amount of memory requested (KB) */
|
||||||
|
uint32_t lanes; /* number of lanes */
|
||||||
|
uint32_t threads; /* maximum number of threads */
|
||||||
|
|
||||||
|
uint32_t version; /* version number */
|
||||||
|
|
||||||
|
allocate_fptr allocate_cbk; /* pointer to memory allocator */
|
||||||
|
deallocate_fptr free_cbk; /* pointer to memory deallocator */
|
||||||
|
|
||||||
|
uint32_t flags; /* array of bool options */
|
||||||
|
} argon2_context;
|
||||||
|
|
||||||
|
int argon2_ctx(argon2_context *context, argon2_type type);
|
||||||
|
|
||||||
|
/* Error codes */
|
||||||
|
typedef enum Argon2_ErrorCodes {
|
||||||
|
ARGON2_OK = ...,
|
||||||
|
|
||||||
|
ARGON2_OUTPUT_PTR_NULL = ...,
|
||||||
|
|
||||||
|
ARGON2_OUTPUT_TOO_SHORT = ...,
|
||||||
|
ARGON2_OUTPUT_TOO_LONG = ...,
|
||||||
|
|
||||||
|
ARGON2_PWD_TOO_SHORT = ...,
|
||||||
|
ARGON2_PWD_TOO_LONG = ...,
|
||||||
|
|
||||||
|
ARGON2_SALT_TOO_SHORT = ...,
|
||||||
|
ARGON2_SALT_TOO_LONG = ...,
|
||||||
|
|
||||||
|
ARGON2_AD_TOO_SHORT = ...,
|
||||||
|
ARGON2_AD_TOO_LONG = ...,
|
||||||
|
|
||||||
|
ARGON2_SECRET_TOO_SHORT = ...,
|
||||||
|
ARGON2_SECRET_TOO_LONG = ...,
|
||||||
|
|
||||||
|
ARGON2_TIME_TOO_SMALL = ...,
|
||||||
|
ARGON2_TIME_TOO_LARGE = ...,
|
||||||
|
|
||||||
|
ARGON2_MEMORY_TOO_LITTLE = ...,
|
||||||
|
ARGON2_MEMORY_TOO_MUCH = ...,
|
||||||
|
|
||||||
|
ARGON2_LANES_TOO_FEW = ...,
|
||||||
|
ARGON2_LANES_TOO_MANY = ...,
|
||||||
|
|
||||||
|
ARGON2_PWD_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
|
||||||
|
ARGON2_SALT_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
|
||||||
|
ARGON2_SECRET_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
|
||||||
|
ARGON2_AD_PTR_MISMATCH = ..., /* NULL ptr with non-zero length */
|
||||||
|
|
||||||
|
ARGON2_MEMORY_ALLOCATION_ERROR = ...,
|
||||||
|
|
||||||
|
ARGON2_FREE_MEMORY_CBK_NULL = ...,
|
||||||
|
ARGON2_ALLOCATE_MEMORY_CBK_NULL = ...,
|
||||||
|
|
||||||
|
ARGON2_INCORRECT_PARAMETER = ...,
|
||||||
|
ARGON2_INCORRECT_TYPE = ...,
|
||||||
|
|
||||||
|
ARGON2_OUT_PTR_MISMATCH = ...,
|
||||||
|
|
||||||
|
ARGON2_THREADS_TOO_FEW = ...,
|
||||||
|
ARGON2_THREADS_TOO_MANY = ...,
|
||||||
|
|
||||||
|
ARGON2_MISSING_ARGS = ...,
|
||||||
|
|
||||||
|
ARGON2_ENCODING_FAIL = ...,
|
||||||
|
|
||||||
|
ARGON2_DECODING_FAIL = ...,
|
||||||
|
|
||||||
|
ARGON2_THREAD_FAIL = ...,
|
||||||
|
|
||||||
|
ARGON2_DECODING_LENGTH_FAIL= ...,
|
||||||
|
|
||||||
|
ARGON2_VERIFY_MISMATCH = ...,
|
||||||
|
} argon2_error_codes;
|
||||||
|
|
||||||
|
#define ARGON2_FLAG_CLEAR_PASSWORD ...
|
||||||
|
#define ARGON2_FLAG_CLEAR_SECRET ...
|
||||||
|
#define ARGON2_DEFAULT_FLAGS ...
|
||||||
|
|
||||||
|
#define ARGON2_MIN_LANES ...
|
||||||
|
#define ARGON2_MAX_LANES ...
|
||||||
|
#define ARGON2_MIN_THREADS ...
|
||||||
|
#define ARGON2_MAX_THREADS ...
|
||||||
|
#define ARGON2_SYNC_POINTS ...
|
||||||
|
#define ARGON2_MIN_OUTLEN ...
|
||||||
|
#define ARGON2_MAX_OUTLEN ...
|
||||||
|
#define ARGON2_MIN_MEMORY ...
|
||||||
|
#define ARGON2_MAX_MEMORY_BITS ...
|
||||||
|
#define ARGON2_MAX_MEMORY ...
|
||||||
|
#define ARGON2_MIN_TIME ...
|
||||||
|
#define ARGON2_MAX_TIME ...
|
||||||
|
#define ARGON2_MIN_PWD_LENGTH ...
|
||||||
|
#define ARGON2_MAX_PWD_LENGTH ...
|
||||||
|
#define ARGON2_MIN_AD_LENGTH ...
|
||||||
|
#define ARGON2_MAX_AD_LENGTH ...
|
||||||
|
#define ARGON2_MIN_SALT_LENGTH ...
|
||||||
|
#define ARGON2_MAX_SALT_LENGTH ...
|
||||||
|
#define ARGON2_MIN_SECRET ...
|
||||||
|
#define ARGON2_MAX_SECRET ...
|
||||||
|
|
||||||
|
uint32_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,
|
||||||
|
uint32_t parallelism, uint32_t saltlen,
|
||||||
|
uint32_t hashlen, argon2_type type);
|
||||||
|
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ffi.compile()
|
||||||
19
tests/test_smoke.py
Normal file
19
tests/test_smoke.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
Since this package doesn't do anything beyond providing bindings, all we can
|
||||||
|
do is trying to ensure that those bindings are functional.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def test_smoke():
|
||||||
|
"""
|
||||||
|
lib and ffi can be imported and looks OK.
|
||||||
|
"""
|
||||||
|
from _argon2_cffi_bindings import ffi, lib
|
||||||
|
|
||||||
|
assert repr(ffi).startswith("<_cffi_backend.FFI object at")
|
||||||
|
assert repr(lib).startswith("<Lib object for")
|
||||||
|
|
||||||
|
assert 19 == lib.ARGON2_VERSION_NUMBER
|
||||||
|
assert 42 == lib.argon2_encodedlen(1, 2, 3, 4, 5, lib.Argon2_id)
|
||||||
79
tox.ini
Normal file
79
tox.ini
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
[flake8]
|
||||||
|
exclude = src/_argon2_cffi_bindings/_ffi.py
|
||||||
|
ignore:
|
||||||
|
# Black vs flake8 conflict
|
||||||
|
E203
|
||||||
|
|
||||||
|
|
||||||
|
# We don't run pre-commit in CI, because we use pre-commit.ci.
|
||||||
|
[gh-actions]
|
||||||
|
python =
|
||||||
|
3.6: py36
|
||||||
|
3.7: py37
|
||||||
|
3.8: py38
|
||||||
|
3.9: py39, manifest
|
||||||
|
3.10: py310, cogCheck
|
||||||
|
pypy-3: pypy3
|
||||||
|
|
||||||
|
|
||||||
|
[tox]
|
||||||
|
envlist = pre-commit,cogCheck,cog,py36,py37,py38,py39,py310,pypy3,system-argon2,manifest,pypi-description
|
||||||
|
isolated_build = true
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:pre-commit]
|
||||||
|
description = Run all pre-commit hooks.
|
||||||
|
basepython = python3.10
|
||||||
|
skip_install = true
|
||||||
|
deps = pre-commit
|
||||||
|
passenv = HOMEPATH # needed on Windows
|
||||||
|
commands = pre-commit run --all-files
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:cog]
|
||||||
|
description = "Update README"
|
||||||
|
skip_install = true
|
||||||
|
deps =
|
||||||
|
cogapp>=3.3.0
|
||||||
|
commands = python -m cogapp -rP README.md
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:cogCheck]
|
||||||
|
description = "Ensure README.md is up to date"
|
||||||
|
skip_install = true
|
||||||
|
deps = {[testenv:cog]deps}
|
||||||
|
commands = python -m cogapp --check -P README.md
|
||||||
|
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
description = Run tests.
|
||||||
|
extras = tests
|
||||||
|
commands =
|
||||||
|
python -m pytest {posargs}
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:system-argon2]
|
||||||
|
description = Run tests against bindings that use a system installation of Argon2.
|
||||||
|
setenv = ARGON2_CFFI_USE_SYSTEM=1
|
||||||
|
extras = tests
|
||||||
|
install_command = pip install {opts} --no-binary=argon2-cffi-bindings {packages}
|
||||||
|
commands =
|
||||||
|
python -m pytest {posargs}
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:manifest]
|
||||||
|
description = Ensure MANIFEST.in is up to date.
|
||||||
|
deps = check-manifest
|
||||||
|
skip_install = true
|
||||||
|
commands = check-manifest
|
||||||
|
|
||||||
|
|
||||||
|
[testenv:pypi-description]
|
||||||
|
description = Ensure README.rst renders on PyPI.
|
||||||
|
skip_install = true
|
||||||
|
deps =
|
||||||
|
twine
|
||||||
|
pip >= 18.0.0
|
||||||
|
commands =
|
||||||
|
pip wheel -w {envtmpdir}/build --no-deps .
|
||||||
|
twine check {envtmpdir}/build/*
|
||||||
Loading…
Reference in New Issue
Block a user