Metadata-Version: 2.1
Name: psypher
Version: 1.0.0
Summary: A modern asymmetric encryption scheme.
Home-page: https://gitee.com/origamizyt/psypher
Author: origamizyt
Author-email: zhaoyitong18@163.com
License: UNKNOWN
Description: # 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:
        ```shell
        $ pip install psypher
        ```
        
        If you want to use the source code directly, make sure you install the `cryptography` dependency.
        
        ```shell
        $ 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`).
        ```py
        >>> 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.
        ```py
        # 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:
        ```py
        >>> 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.
        ```py
        >>> 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.
        ```py
        >>> 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:
        ```py
        >>> 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.
        ```py
        >>> 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:
        ```py
        >>> 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:
        ```py
        # 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:
        ```py
        >>> from psypher.scheme import Secp256k1AesGcmScheme
        >>> s1 = Secp256k1AesGcmScheme.generate()
        ```
        
        You can also customize the schemes:
        ```py
        >>> 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](https://github.com/pyca/cryptography).
        
        This software is licensed under the [MIT License](https://opensource.org/licenses/MIT). For more information, see the [License Text](LICENSE).
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
