Digital Signatures

Digital signatures are somewhat similar to signatures in real life; a verified signature proves to the verifier that at some point, the document was signed by someone with knowledge of the private key.

from monocypher.signing import SigningKey

# Generate a random SigningKey -- this must be kept secret
signing_key = SigningKey.generate()
# This can be published
verify_key = signing_key.verify_key

signed = alice_sk.sign(b'hello there!')

Verifying signatures:

assert verify_key.verify(signed)

# You can also verify the detached signature
assert signed.msg == message
assert verify_key.verify(message, sig=signed.sig)

Reference

class monocypher.signing.SigningKey(sk)

EdDSA private key. This should be kept secret.

Parameters:

sk – The secret key (bytes), should be KEY_SIZE bytes long.

encode()

Return the signing key as bytes.

Return type:

bytes

KEY_SIZE = 32

Length of a secret key.

SIG_SIZE = 64

Length of a signature.

classmethod generate()

Generates a random SigningKey object.

Return type:

SigningKey

sign(msg)

Signs the given msg.

Return type:

SignedMessage

to_private_key()

Converts from a SigningKey to a PrivateKey object. The conversion is one-way and deterministic. Note that although the conversion is sound, you should not (without good reason) use the same private key for signing and key-exchange.

Return type:

PrivateKey

property verify_key

Return the corresponding VerifyKey object.

Return type:

VerifyKey

class monocypher.signing.VerifyKey(pk)

EdDSA public key. This can be published.

Parameters:

pk – The public key (bytes), should be KEY_SIZE bytes long.

encode()

Return the verifying key as bytes.

Return type:

bytes

KEY_SIZE = 32

Length of a public key.

SIG_SIZE = 64

Length of a signature.

to_public_key()

Converts from a VerifyKey to a PublicKey object. See notes about using the same key for both signing and key-exchange in SigningKey.to_private_key.

Return type:

PublicKey

verify(signed, sig=None)

Verify the given signed message. If sig is None, then the signature is assumed to be prepended to signed. Return the original message if the verification succeeds, otherwise SignatureError is raised.

Parameters:
class monocypher.signing.SignedMessage

A subclass of bytes representing a signed message. By default, the signature will be prepended to the message.

property msg

Returns the message part.

Return type:

bytes

property sig

Returns the signature part.

Return type:

bytes

exception monocypher.signing.SignatureError

Extras

The SigningKey and VerifyKey classes both implement equality (between objects of the same type) and conversion to bytes, as well as hashing:

>>> sk_1 = SigningKey.generate()
>>> sk_2 = SigningKey.generate()
>>> sk_1 == sk_2
False
>>> sk_1.verify_key == VerifyKey(bytes(sk_1.verify_key))
True
>>> hash(sk_1)
...
>>> hash(sk_1.verify_key)
...

Implementation

sign() and verify() both use PureEdDSA with Curve25519 and Blake2b, (RFC 8032). This is the same as Ed25519 with Blake2b instead of SHA-512.

to_private_key() and to_public_key() use the crypto_from_eddsa_private and crypto_from_eddsa_public functions from Monocypher respectively, which converts from EdDSA keys to X25519 keys.