0 purchases
psypher 1.0.0
Psypher - A modern asymmetric encryption scheme.
Psypher is a modern cryptography module providing high-level security recipes with simple interfaces. It is built for securing communication through insecure channels.
Installation
This module is available via PyPI:
$ pip install psypher
If you want to use the source code directly, make sure you install the cryptography dependency.
$ pip install cryptography
Basic Usage
All the interface Psypher provides is accessible through the Scheme interface. Use the default static method to obtain an instance of the default scheme (curve25519-chacha20poly1305).
>>> from psypher import Scheme
>>> s1, s2 = Scheme.default(), Scheme.default()
>>> s1.__class__.__name__
'Curve25519ChaCha20Poly1305Scheme'
The private and public key is accessible with the privateKey and publicKey properties. The basic usage of these keys are shown below.
# key export (also suitable for public keys)
key1 = s1.privateKey.export() # bytes
key2 = s2.privateKey.exportJson() # str
# key import (also suitable for public keys)
psypher.secret.Curve25519PrivateKey.importKey(key1)
psypher.secret.Curve25519PrivateKey.importJson(key2)
# encrypted key export (private keys only)
key1 = s1.privateKey.secureExport(b'password')
key2 = s2.privateKey.secureExportJson(b'password')
# encrypted key import (private keys only)
psypher.secret.Curve25519PrivateKey.importKey(key1, b'password')
psypher.secret.Curve25519PrivateKey.importJson(key2, b'password')
# key fingerprint (public keys only)
print(s1.publicKey.digest)
When using encrypted key export, the default behaviours is to derive the wrapping key from the password using PBKDF2. However, you can specify derive=False to disable this kind of behaviour and to use your material as key directly.
IPublicKey.digest is a cached property, so it might not behave as you expect it to be. See the Advanced Usage / Cache Mode to learn more.
The export, exportJson methods is also defined on the scheme as a shortcut to the public key. Use the receive and receiveJson methods to receive remote key from peers:
>>> s1.receive(s2.export())
>>> s2.receiveJson(s1.exportJson())
Use the shareSecret property to calculate the negotiated shared secret. This property is CACHED, that means it only evaluates once. For detailed information about caching, please navigate to the Advanced Usage / Cache Mode section.
>>> s1.sharedSecret == s2.sharedSecret
True
To generate the digital signature of specific message, use the sign method. Call verify on the other side to verify the message. You can only verify messages signed by your peer. The signature generated is deterministic.
>>> data = b'My telephone number is 123456!'
>>> signature = s1.sign(data)
>>> s2.verify(data, signature)
True
>>> s2.verify(b'My telephone number is 654321!', signature)
False
If you just want to check the integrity of your message therefore don't require such cryptographical strength of your signature, or if you need a shorter signature value, the integritySign method may suits you. It uses HMAC to sign the message, producing only 32 bytes output. Likewise, the integrityVerify method can be used to verify this signature:
>>> data = b'My telephone number is 123456!'
>>> signature = s1.integritySign(data)
>>> s2.integrityVerify(data, signature)
True
>>> s2.integrityVerify(b'My telephone number is 654321!', signature)
False
To encrypt your message, use the encrypt method. Call decrypt on the other side to decrypt your message. You can only decrypt messages encrypted by your peer. The ciphertext is different each time you call encrypt, even if you are encrypting the same message.
>>> data = b'The darkest secret lies here.'
>>> ciphertext = s2.encrypt(data)
>>> s1.decrypt(ciphertext) == data
True
>>> from psypher.errors import InvalidCiphertext
>>> try:
... s1.decrypt(b'This is absolutely illegal')
... except InvalidCiphertext:
... pass
Advanced Usage
Below are some complicated usages of this module beyond the normal usage.
Cache Mode
The cache mode is enabled by default, which means certain methods or property will only be calculated once and cached. Cached items includes IPublicKey.digest and <KeyPairClass>.sharedSecret. You can disable caching globally with the following statements:
>>> from psypher import cache
>>> cache.setenabled(False)
You can access the cache object through the unbound version of the method or property. Here are some usages:
# query
from psypher.secret import IPublicKey
IPublicKey.digest.fget.enabled
# partially disable
IPublicKey.digest.fget.enabled = False
EccKeyPair.sharedSecret.fget.enabled = False
# clear cache for all instances
Curve25519KeyPair.sharedSecret.fget.clearCache()
If you disabled the cache globally, the enabled property will return False on every instance, even if you set it to True.
Customize Scheme
The scheme object is located in the psypher.cipher module. A scheme is consisted of two parts - the key pair and the symmetric encryptor. You could customize these parts.
The module provides two built-in schemes: Curve15519ChaCha20Poly1305Scheme, which is the default, and Secp256k1AesGcmScheme, which is recommended to use in commercial circumstances. These schemes produces the ciphertext with similar structure:
Curve25519ChaCha20Poly1305
Input: plain text (X bytes)
Output:
EphKey
HkdfSalt
AeadNonce
Ciphertext
AeadTag
Total
32 bytes
16 bytes
12 bytes
X bytes
16 bytes
76+X bytes
Secp256k1AesGcm:
Input: plain text (X bytes)
Output:
EphKey
HkdfSalt
AeadNonce
Ciphertext
AeadTag
Total
65 bytes
16 bytes
12 bytes
X bytes
16 bytes
109+X bytes
These schemes can be found in the psypher.scheme module:
>>> from psypher.scheme import Secp256k1AesGcmScheme
>>> s1 = Secp256k1AesGcmScheme.generate()
You can also customize the schemes:
>>> from psypher.cipher import AesGcmEncryptor
>>> from psypher.secret import Curve25519KeyPair
>>> from psypher.scheme import Scheme
>>> s1 = Scheme(Curve25519KeyPair.generate(), AesGcmEncryptor)
To fully build your own customized scheme, you may want to inherit from the IKeyPair class. You must implement the IPrivateKey and IPublicKey interfaces too. The IEncryptor interface however, is a static interface, only containing static methods. For more details, please see the source code.
Support & License
This module is built on the pyca/cryptography library. See their Github Repository.
This software is licensed under the MIT License. For more information, see the License Text.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.