# P.S.O. Poseidon
[](https://crates.io/crates/pso-poseidon)
[](https://github.com/psonet/pso-poseidon/releases)
[](https://github.com/psonet/pso-poseidon/actions/workflows/ci.yml)
**pso-poseidon** is a [Poseidon](https://eprint.iacr.org/2019/458) hash
implementation in Rust created for [PSO](https://github.com/psonet) based on [light-poseidon](https://github.com/Lightprotocol/light-poseidon/) library.
## Parameters
The library provides pre-generated parameters over the BN254 curve, however
it can work with any parameters provided as long as developers take care
of generating the round constants.
Parameters provided by the library are:
* *x^5* S-boxes
* width - *2 ≤ t ≤ 13*
* inputs - *1 ≤ n ≤ 12*
* 8 full rounds and partial rounds depending on *t*: *[56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65]*
## Output type
`Poseidon` type implements two traits which serve the purpose
of returning the calculated hash in different representations:
* `PoseidonHasher` with the `hash` method which returns
`ark_ff::PrimeField`. Might be useful if you want
to immediately process the result with an another library which works with
`ark_ff::PrimeField` types.
## Examples
With `PoseidonHasher` trait and `ark_ff::PrimeField` result:
```rust
use ark_bn254::Fr;
use ark_ff::PrimeField;
use pso_poseidon::{Poseidon, PoseidonHasher};
let mut poseidon = Poseidon::<Fr>::new_circom(2).unwrap();
let input1 = Fr::from_le_bytes_mod_order(&[1u8; 32]);
let input2 = Fr::from_le_bytes_mod_order(&[2u8; 32]);
let hash = poseidon.hash(&[input1, input2]).unwrap();
// Do something with `hash`.
```
## Poseidon2
`Poseidon2` is a separate, generic BN254 **Poseidon2** hash, bit-compatible
with noir's in-circuit `poseidon2` (Barretenberg's permutation + sponge). Use
it for off-circuit hashing that must reproduce an in-circuit Poseidon2 result.
It shares no parameters with the circom-compatible `Poseidon` above —
Poseidon2 is a distinct construction. BN254 is built in via
`Poseidon2::<Fr>::new()`; other fields supply their own constants.
```rust
use ark_bn254::Fr;
use pso_poseidon::{Poseidon2, PoseidonHasher};
let mut poseidon2 = Poseidon2::<Fr>::new();
let _hash = poseidon2.hash(&[Fr::from(1u64), Fr::from(2u64)]).unwrap();
```
## Field Arithmetic
This library uses [ark-ff](https://github.com/arkworks-rs/algebra) for field arithmetic. While ark-ff carries an academic disclaimer, it is widely adopted in production by major projects including [Aleo](https://github.com/AleoNet/snarkVM), [Penumbra](https://github.com/penumbra-zone/penumbra), [Mina (Kimchi)](https://github.com/o1-labs/proof-systems), and [Espresso Systems](https://github.com/EspressoSystems).
## Implementation
The implementation is compatible with the
[original SageMath implementation](https://extgit.iaik.tugraz.at/krypto/hadeshash/-/tree/master/),
but it was also inspired by the following ones:
* [circomlibjs](https://github.com/iden3/circomlibjs)
* [zero-knowledge-gadgets](https://github.com/webb-tools/zero-knowledge-gadgets)
* [light-poseidon](https://github.com/Lightprotocol/light-poseidon/)
## Security
This library has been audited by [Veridise](https://veridise.com/). You can
read the audit report [here](https://github.com/Lightprotocol/light-poseidon/blob/main/assets/audit.pdf).
## Verifying releases
Releases tagged from `v0.3.5` onward ship sigstore cosign signatures + SLSA build-provenance attestations for every artifact. See [SECURITY.md](SECURITY.md) for the threat model and the copy-pasteable verify recipe.
Quick check:
```sh
TAG=v0.3.5
ARTIFACT=pso-poseidon-${TAG#v}.crate
gh release download "$TAG" --repo psonet/pso-poseidon \
--pattern "$ARTIFACT" --pattern "$ARTIFACT.sig" --pattern "$ARTIFACT.pem"
cosign verify-blob \
--certificate "$ARTIFACT.pem" --signature "$ARTIFACT.sig" \
--certificate-identity-regexp \
'^https://github\.com/psonet/pso-poseidon/\.github/workflows/ci\.yml@refs/(heads/main|tags/v[0-9]+\.[0-9]+\.[0-9]+)$' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"$ARTIFACT"
```