Skip to main content

Provides OpenPGP facilities using Sequoia-PGP library

Project description

PySequoia

PyPI version PyPI Downloads CI

This library provides OpenPGP facilities in Python through the Sequoia PGP library. If you need to work with encryption and digital signatures using an IETF standardized protocol, this package is for you!

Note: This is a work in progress. The API is not stable!

Building

set -euxo pipefail
python -m venv .env
source .env/bin/activate
pip install maturin
maturin develop

Installing

PySequoia can be installed through pip:

pip install pysequoia

Note that since pysequoia is implemented largely in Rust, a Rust toolchain is necessary for the installation to succeed.

Testing

This entire document is used for end-to-end integration tests that exercise the package's API surface.

The tests assume that these keys and cards exist:

# generate a key with password
gpg --batch --pinentry-mode loopback --passphrase hunter22 --quick-gen-key passwd@example.com
gpg --batch --pinentry-mode loopback --passphrase hunter22 --export-secret-key passwd@example.com > passwd.pgp

# generate a key without password
gpg --batch --pinentry-mode loopback --passphrase '' --quick-gen-key no-passwd@example.com future-default
gpg --batch --pinentry-mode loopback --passphrase '' --export-secret-key no-passwd@example.com > no-passwd.pgp

# initialize dummy OpenPGP Card
sh /start.sh
echo 12345678 > pin
CARD_ADMIN="opgpcard admin --card 0000:00000000 --admin-pin pin"
$CARD_ADMIN import full-key.asc
$CARD_ADMIN name "John Doe"
$CARD_ADMIN url "https://example.com/key.pgp"
$CARD_ADMIN touch --key SIG --policy Fixed
$CARD_ADMIN touch --key DEC --policy Off
$CARD_ADMIN touch --key AUT --policy Fixed

Functions

All examples assume that these basic classes have been imported:

from pysequoia import Cert

encrypt

Signs and encrypts a string to one or more recipients:

from pysequoia import encrypt

s = Cert.from_file("passwd.pgp")
r = Cert.from_bytes(open("wiktor.asc", "rb").read())
bytes = "content to encrypt".encode("utf8")
encrypted = encrypt(signer = s.secrets.signer("hunter22"), recipients = [r], bytes = bytes).decode("utf8")
print(f"Encrypted data: {encrypted}")

decrypt

Decrypts data:

from pysequoia import decrypt

sender = Cert.from_file("no-passwd.pgp")
receiver = Cert.from_file("passwd.pgp")

content = "Red Green Blue"

encrypted = encrypt(signer = sender.secrets.signer(), recipients = [receiver], bytes = content.encode("utf8"))

decrypted = decrypt(decryptor = receiver.secrets.decryptor("hunter22"), bytes = encrypted)

assert content == decrypted.bytes.decode("utf8");

sign

Signs data and returns armored output:

from pysequoia import sign

s = Cert.from_file("signing-key.asc")
signed = sign(s.secrets.signer(), "data to be signed".encode("utf8"))
print(f"Signed data: {signed}")

Certificates

The Cert class represents one OpenPGP certificate (commonly called a "public key").

This package additionally verifies the certificate using Sequoia PGP's StandardPolicy. This means that certificates using weak cryptography can fail to load, or present a different view than in other OpenPGP software (e.g. if a User ID uses SHA-1 in its back-signature, it may be missing from the list of User IDs returned by this package).

Certificates have two forms, one is ASCII armored and one is raw bytes:

cert = Cert.generate("Test <test@example.com>")

print(f"Armored cert: {cert}")
print(f"Bytes of the cert: {cert.bytes()}")

Parsing

Certificates can be parsed from files (Cert.from_file) or bytes in memory (Cert.from_bytes).

cert1 = Cert.generate("Test <test@example.com>")
buffer = cert1.bytes()

parsed_cert = Cert.from_bytes(buffer)
assert str(parsed_cert.user_ids[0]) == "Test <test@example.com>"

They can also be picked from "keyring" files (Cert.split_file) or bytes in memory (Cert.split_bytes) which are collections of binary certificates.

cert1 = Cert.generate("Test 1 <test-1@example.com>")
cert2 = Cert.generate("Test 2 <test-2@example.com>")
cert3 = Cert.generate("Test 3 <test-3@example.com>")

buffer = cert1.bytes() + cert2.bytes() + cert3.bytes()
certs = Cert.split_bytes(buffer)
assert len(certs) == 3

generate

Creates a new general purpose key with a given User ID:

alice = Cert.generate("Alice <alice@example.com>")
fpr = alice.fingerprint
print(f"Generated cert with fingerprint {fpr}:\n{alice}")

Multiple User IDs can be passed as a list to the generate function:

cert = Cert.generate(user_ids = ["First", "Second", "Third"])
assert len(cert.user_ids) == 3

Newly generated certificates are usable in both encryption and signing contexts:

alice = Cert.generate("Alice <alice@example.com>")
bob = Cert.generate("Bob <bob@example.com>")

bytes = "content to encrypt".encode("utf8")

encrypted = encrypt(signer = alice.secrets.signer(), recipients = [bob], bytes = bytes)
print(f"Encrypted data: {encrypted}")

merge

Merges packets from a new version into an old version of a certificate:

old = Cert.from_file("wiktor.asc")
new = Cert.from_file("wiktor-fresh.asc")
merged = old.merge(new)
print(f"Merged, updated cert: {merged}")

User IDs

Listing existing User IDs:

cert = Cert.from_file("wiktor.asc")
user_id = cert.user_ids[0]
assert str(user_id).startswith("Wiktor Kwapisiewicz")

Adding new User IDs:

cert = Cert.generate("Alice <alice@example.com>")
assert len(cert.user_ids) == 1;

cert = cert.add_user_id(value = "Alice <alice@company.invalid>", certifier = cert.secrets.certifier())

assert len(cert.user_ids) == 2;

Revoking User IDs:

cert = Cert.generate("Bob <bob@example.com>")

cert = cert.add_user_id(value = "Bob <bob@company.invalid>", certifier = cert.secrets.certifier())
assert len(cert.user_ids) == 2

# create User ID revocation
revocation = cert.revoke_user_id(user_id = cert.user_ids[1], certifier = cert.secrets.certifier())

# merge the revocation with the cert
cert = Cert.from_bytes(cert.bytes() + revocation.bytes())
assert len(cert.user_ids) == 1

Notations

Notations are small pieces of data that can be attached to signatures (and, indirectly, to User IDs).

The following example reads and displays a Keyoxide proof URI:

cert = Cert.from_file("wiktor.asc")
user_id = cert.user_ids[0]
notation = user_id.notations[0]

assert notation.key == "proof@metacode.biz";
assert notation.value == "dns:metacode.biz?type=TXT";

Notations can also be added:

from pysequoia import Notation

cert = Cert.from_file("signing-key.asc")

# No notations initially
assert len(cert.user_ids[0].notations) == 0;

cert = cert.set_notations(cert.secrets.certifier(), [Notation("proof@metacode.biz", "dns:metacode.biz")])

# Has one notation now
print(str(cert.user_ids[0].notations))
assert len(cert.user_ids[0].notations) == 1;

# Check the notation data
notation = cert.user_ids[0].notations[0]

assert notation.key == "proof@metacode.biz";
assert notation.value == "dns:metacode.biz";

Key expiration

Certs have an expiration getter for retrieving the current key expiry time:

cert = Cert.from_file("signing-key.asc")

# Cert does not have any expiration date:
assert cert.expiration is None

cert = Cert.from_file("wiktor.asc")
# Cert expires on New Year's Eve
assert str(cert.expiration) == "2022-12-31 12:00:02+00:00"

Key expiration can also be adjusted with set_expiration:

from datetime import datetime

cert = Cert.from_file("signing-key.asc")

# Cert does not have any expiration date:
assert cert.expiration is None

# Set the expiration to some specified point in time
expiration = datetime.fromisoformat("2021-11-04T00:05:23+00:00")
cert = cert.set_expiration(expiration = expiration, certifier = cert.secrets.certifier())
assert str(cert.expiration) == "2021-11-04 00:05:23+00:00"

Key revocation

Certs can be revoked. While expiration makes the key unusable temporarily to encourage the user to refresh a copy revocation is irreversible.

cert = Cert.generate("Test Revocation <revoke@example.com>")
revocation = cert.revoke(certifier = cert.secrets.certifier())

# creating revocation signature does not revoke the key
assert not cert.is_revoked

# importing revocation signature marks the key as revoked
revoked_cert = Cert.from_bytes(cert.bytes() + revocation.bytes())
assert revoked_cert.is_revoked

Secret keys

Certificates generated through Cert.generate() contain secret keys and can be used for signing and decryption.

To avoid accidental leakage secret keys are never directly printed when the Cert is written to a string. To enable this behavior use Cert.secrets. secrets returns None on certificates which do not contain any secret key material ("public keys").

c = Cert.generate("Testing key <test@example.com>")
assert c.has_secret_keys

# by default only public parts are exported
public_parts = Cert.from_bytes(f"{c}".encode("utf8"))
assert not public_parts.has_secret_keys
assert public_parts.secrets is None

# to export secret parts use the following:
private_parts = Cert.from_bytes(f"{c.secrets}".encode("utf8"))
assert private_parts.has_secret_keys

Certificate management

CertD integration

This library exposes OpenPGP Certificate Directory integration, which allows storing and retrieving OpenPGP certificates in a persistent way directly in the file system.

Note that this will not allow you to read GnuPG-specific key directories. Cert-D does not allow certificate removal.

from pysequoia import Store

cert = Cert.from_file("wiktor.asc")
s = Store("/tmp/store")
s.put(cert)
assert s.get(cert.fingerprint) != None

The certificate is now stored in the given directory and can be retrieved later by its fingerprint:

s = Store("/tmp/store")
assert s.get("653909a2f0e37c106f5faf546c8857e0d8e8f074") != None

OpenPGP Cards

There's an experimental feature allowing communication with OpenPGP Cards (like YubiKey or Nitrokey).

from pysequoia import Card

# enumerate all cards
all = Card.all()

# open card by card ident
card = Card.open("0000:00000000")

print(f"Card ident: {card.ident}")
assert card.cardholder == "John Doe"
assert card.cert_url == "https://example.com/key.pgp"

Cards provide keys property that can be used to see which keys are imported on the card:

keys = card.keys
print(f"Keys: {keys}")
assert len(keys) == 3

assert keys[0].fingerprint == "ddc3e03c91fb52ca2d95c2444566f2743ed5f382"
assert "sign" in keys[0].usage
assert keys[0].touch_required

assert keys[1].fingerprint == "689e152a7420be13dcaf2c142ac27adc1db9395e"
assert "decrypt" in keys[1].usage
assert not keys[1].touch_required

assert keys[2].fingerprint == "731fbca93ce9821347bf8e696444723371d3c650"
assert "authenticate" in keys[2].usage
assert keys[2].touch_required

Cards can be used for signing data:

signer = card.signer("123456")

signed = sign(signer, "data to be signed".encode("utf8"))
print(f"Signed data: {signed}")

As well as for decryption:

decryptor = card.decryptor("123456")

sender = Cert.from_file("passwd.pgp")
receiver = Cert.from_file("full-key.asc")

content = "Red Green Blue"

encrypted = encrypt(signer = sender.secrets.signer("hunter22"), recipients = [receiver], bytes = content.encode("utf8"))

print(f"Encrypted data: {encrypted}")

decrypted = decrypt(decryptor = decryptor, bytes = encrypted)

assert content == decrypted.bytes.decode("utf8");

Note that while this package allows using cards for signing and decryption, the provisioning process is not supported. OpenPGP card tools can be used to initialize the card.

License

This project is licensed under Apache License, Version 2.0.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the package by you shall be under the terms and conditions of this license, without any additional terms or conditions.

Sponsors

My work was supported by these generous organizations (alphabetical order):

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pysequoia-0.1.21.tar.gz (272.6 kB view details)

Uploaded Source

Built Distributions

pysequoia-0.1.21-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-cp312-none-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.12 Windows x86-64

pysequoia-0.1.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-cp312-cp312-macosx_11_0_arm64.whl (1.8 MB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

pysequoia-0.1.21-cp312-cp312-macosx_10_7_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.12 macOS 10.7+ x86-64

pysequoia-0.1.21-cp311-none-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.11 Windows x86-64

pysequoia-0.1.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-cp311-cp311-macosx_11_0_arm64.whl (1.8 MB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

pysequoia-0.1.21-cp311-cp311-macosx_10_7_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.11 macOS 10.7+ x86-64

pysequoia-0.1.21-cp310-none-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.10 Windows x86-64

pysequoia-0.1.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-cp310-cp310-macosx_11_0_arm64.whl (1.8 MB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

pysequoia-0.1.21-cp310-cp310-macosx_10_7_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.10 macOS 10.7+ x86-64

pysequoia-0.1.21-cp39-none-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.9 Windows x86-64

pysequoia-0.1.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-cp38-none-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.8 Windows x86-64

pysequoia-0.1.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

pysequoia-0.1.21-cp37-none-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.7 Windows x86-64

pysequoia-0.1.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

File details

Details for the file pysequoia-0.1.21.tar.gz.

File metadata

  • Download URL: pysequoia-0.1.21.tar.gz
  • Upload date:
  • Size: 272.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.3.2

File hashes

Hashes for pysequoia-0.1.21.tar.gz
Algorithm Hash digest
SHA256 4fd7ae2dbf4c426d04d3692230e00fa5d0b3b64f9fb91708ff21246738c03550
MD5 874be466e7175008dd62a14c580da450
BLAKE2b-256 b953dcacdd79f5564306b5a6033440910240d06e78140b494fb574153e3b05cf

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 91391132abd75d96a579b763b383a090af0807df4d2299a27d70f19e548a78a2
MD5 480af0ffd5b13ae65a4b18e2501845ee
BLAKE2b-256 7f215d9f92553934fd20c2a2c65253fe8ccadf6ed154ccc16d87fc207352b870

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cfe0f8dc7b7aaa84cbc730a02c132e9fea5de6989e6e790ebc08a1db7d849aaf
MD5 8afa0847dd57ed0681f3c194c5623fd7
BLAKE2b-256 96e558edc805349a436146f3855e3e3051836f5833c5cda14da46960286acb57

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 71d118df8ba8af3ac72a802e72a651a2050a7c7ae38eeb8de4b1f583acffab38
MD5 2e71a624121184f7bd17d865bf561db2
BLAKE2b-256 e54a890ea07ef6817e62297fa89cfac208a17ffe2ad2d09349c2e5bb6c43d205

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fe010dec259f9a0b6ec44c3894eb8cb75b772e645feff374fd70f0ac0d9a3291
MD5 83dbe93e190ae12c7682239cd99e488e
BLAKE2b-256 e78f03f5e629f4ccf1343e6f51dcbe0e599733e07a2e7933c87fd097c79861b3

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp312-none-win_amd64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp312-none-win_amd64.whl
Algorithm Hash digest
SHA256 e6c3dbd1250bd55cd5f76415efdf9193504a13522af1a6482da528ff3acc6bc3
MD5 b0df2533b102014698d4898da2f7c7aa
BLAKE2b-256 ca175ebc20502166a754d15300172a9ee0c4eb48668b1a170ee78c829e42a6e3

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0064ea54a6f5280b4a1299e2bcb8e7870bb2eaa74a1ee00e4d41c1681c7b26dd
MD5 dba6ed54d1cd0d1fa01a89a92fd7bdfb
BLAKE2b-256 59fe1e22a08841c793746a39b05a55f1b8b180a92da6ee519ba7b7f82805ce93

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 24a17d1df7395afe6f840bb777d5daffedb921301400e9006d318906e772804d
MD5 f520382f9f3e47c3ac12eb1c170af7a3
BLAKE2b-256 fbd6ca653ff9ca0c45e971056338e4b5fd403d9f3af3f5fc05236e25321eaca4

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp312-cp312-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp312-cp312-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 889e543b0533f585ae3c0c4d1f8b5c7cab92189b03c8a13aaa88dd57d916e3c3
MD5 ca1f16864aa58917b0859385a5a833d9
BLAKE2b-256 f493c06e018c9bc14012e9635b3106596a456337f138dacd81af97817d3f7a16

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp311-none-win_amd64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp311-none-win_amd64.whl
Algorithm Hash digest
SHA256 5b9d280f499539ca61dca1c0fef189396d1a2ac4ed6cc0305ec3c2653391faff
MD5 1b5d2a28b0c9bbef7a2b7a36ec5d7dcb
BLAKE2b-256 b558efe203d567cbf770b06d7917b1503b8941df61b51fe7fd79de68dbd6f999

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 52466b7c389268aaf3111dba9666bf7968c329878019e1d4475b4532386364b0
MD5 44e08a95c34d16ff51df6702f9ff9186
BLAKE2b-256 5fcb32f2617c2c7c415134f638caad449b091f5c4350bd19a37c3746ccd5cb79

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 26b4ad59938d3de53d2a686a4fd599f39c651d2f1a90377dd70b51fd3a0a6032
MD5 27dd22dc4394f26c3b97b9e82944c565
BLAKE2b-256 f9dcf3992ee76fd76db769c94bd4a7330af88c74e3e3c8b61a257ed9b46dcf0a

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp311-cp311-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp311-cp311-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 f050316b2306ae74befd8aa33f9f2a513eaa8706b8757af8bc3db90a9e84fa97
MD5 3ca000f8703fd5ca30f3fcabcdccaeda
BLAKE2b-256 211c78f37d301b5b0eaf9edca0787630c2946a92bd61ad1b1e62a19332266e16

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp310-none-win_amd64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp310-none-win_amd64.whl
Algorithm Hash digest
SHA256 40060951677fbacd4b0f690c87223b1b1eb5240ab4bb2fb37308536efb7b0f8c
MD5 b0825442103ac4f4e580bf71d601f26e
BLAKE2b-256 44d4bd974f68222b80638573052e4500cdd00b84a06f63569aa3854f2fd18fe6

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 02f985c487f41057ea5f03c666784c42bc9477c8d36be611594c00afa2cb10ec
MD5 71b1fd487fe434040fc48d871bc597e6
BLAKE2b-256 94aeebc3192eb1247b7261ac98dbd5543f0aaf7e3d574b1b1f0ffdbdb00fd4c9

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bc79360d79556a7bf6782f7b95797cf8f0ba52eb542420241ffd30e730e05e43
MD5 13563a53dd098dbd8d7b3effa8566eb0
BLAKE2b-256 ce3aae5a5d69ce5bde8b44034b97e4ee0d86d98f0de32a5976e9677b6cc34a0d

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp310-cp310-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp310-cp310-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 4cfb28683ea3e0e5c9618d20454b470f3c4a1e36977b47bc0b18f86f4cb63073
MD5 fadef878f5b8106fcf34eff8a5d1bf5b
BLAKE2b-256 2af804fd61ae3b56ed664484bfda136cdc460ba12a38c8fa917cb46a437c5ec6

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp39-none-win_amd64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp39-none-win_amd64.whl
Algorithm Hash digest
SHA256 032a7042f6930be662536c769136d07a131b8bfcc6fe980d8cf03c57b9656445
MD5 2ba1a0124aa9a24288bf48f71452844d
BLAKE2b-256 7988ed15982c80493c3e2369565a75da040e3cbf658653169af82d074835f0a5

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9c3c3c176a37d5b475986ef6cab914ff8295cc1e852c922ea11e742149ca13f7
MD5 7a1d9d5322c8263488f13a797637ec80
BLAKE2b-256 654d6c45673a1cc4f387eb0382eb2c8ea5fea86d5ba0d4f1ab7a3a1fc7bcf0df

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp38-none-win_amd64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp38-none-win_amd64.whl
Algorithm Hash digest
SHA256 97a29bb3660bb0f2bee0497a2b3b2646662626c4903545eec0925529dcfc36c7
MD5 ceeaf236513c54bf6544c84f85de47f0
BLAKE2b-256 47267c1db0cfee91673347fc5005c3a8910a69b92b5fa1d3553863c3ee4a6c6d

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 387de474823da86f14bf8d2fc5e968ac37a45a1e80d23520fb1865bf44dfea05
MD5 1f90bcece7224268222b9eab208ae2e7
BLAKE2b-256 afe92c37d0d8c136f772aabe973754433581636cdfc50ad0512d2ce77a139e50

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp37-none-win_amd64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp37-none-win_amd64.whl
Algorithm Hash digest
SHA256 556895e88b0bea48dd1e3c1de03607898e6f80624f22a5f34e191ed8d2fcb3da
MD5 aca8bc4be2ce86b188a7e25aaa453182
BLAKE2b-256 b234c616add5ae3ac10ee0f3af30c4627490dfa9d0bf710f66ee451429d566ff

See more details on using hashes here.

File details

Details for the file pysequoia-0.1.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pysequoia-0.1.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 dd5343b84aaadec4393f4ef40109e9aa70c7795d5f774e82cef72c30df9baf54
MD5 80f59bedad7e2dfc8ef2a5198a60a24b
BLAKE2b-256 f2a9a63c779ec0ba68c79e26bc8100d3307b803eea92e2f6e4b55ef5face9d64

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page