tuxbot-bot/venv/lib/python3.7/site-packages/nacl/signing.py

217 lines
7.1 KiB
Python
Raw Normal View History

2019-12-16 18:12:10 +01:00
# Copyright 2013 Donald Stufft and individual contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
import nacl.bindings
from nacl import encoding
from nacl import exceptions as exc
from nacl.public import (PrivateKey as _Curve25519_PrivateKey,
PublicKey as _Curve25519_PublicKey)
from nacl.utils import StringFixer, random
class SignedMessage(bytes):
"""
A bytes subclass that holds a messaged that has been signed by a
:class:`SigningKey`.
"""
@classmethod
def _from_parts(cls, signature, message, combined):
obj = cls(combined)
obj._signature = signature
obj._message = message
return obj
@property
def signature(self):
"""
The signature contained within the :class:`SignedMessage`.
"""
return self._signature
@property
def message(self):
"""
The message contained within the :class:`SignedMessage`.
"""
return self._message
class VerifyKey(encoding.Encodable, StringFixer, object):
"""
The public key counterpart to an Ed25519 SigningKey for producing digital
signatures.
:param key: [:class:`bytes`] Serialized Ed25519 public key
:param encoder: A class that is able to decode the `key`
"""
def __init__(self, key, encoder=encoding.RawEncoder):
# Decode the key
key = encoder.decode(key)
if not isinstance(key, bytes):
raise exc.TypeError("VerifyKey must be created from 32 bytes")
if len(key) != nacl.bindings.crypto_sign_PUBLICKEYBYTES:
raise exc.ValueError(
"The key must be exactly %s bytes long" %
nacl.bindings.crypto_sign_PUBLICKEYBYTES,
)
self._key = key
def __bytes__(self):
return self._key
def __hash__(self):
return hash(bytes(self))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
def __ne__(self, other):
return not (self == other)
def verify(self, smessage, signature=None, encoder=encoding.RawEncoder):
"""
Verifies the signature of a signed message, returning the message
if it has not been tampered with else raising
:class:`~nacl.signing.BadSignatureError`.
:param smessage: [:class:`bytes`] Either the original messaged or a
signature and message concated together.
:param signature: [:class:`bytes`] If an unsigned message is given for
smessage then the detached signature must be provided.
:param encoder: A class that is able to decode the secret message and
signature.
:rtype: :class:`bytes`
"""
if signature is not None:
# If we were given the message and signature separately, combine
# them.
smessage = signature + smessage
# Decode the signed message
smessage = encoder.decode(smessage)
return nacl.bindings.crypto_sign_open(smessage, self._key)
def to_curve25519_public_key(self):
"""
Converts a :class:`~nacl.signing.VerifyKey` to a
:class:`~nacl.public.PublicKey`
:rtype: :class:`~nacl.public.PublicKey`
"""
raw_pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(self._key)
return _Curve25519_PublicKey(raw_pk)
class SigningKey(encoding.Encodable, StringFixer, object):
"""
Private key for producing digital signatures using the Ed25519 algorithm.
Signing keys are produced from a 32-byte (256-bit) random seed value. This
value can be passed into the :class:`~nacl.signing.SigningKey` as a
:func:`bytes` whose length is 32.
.. warning:: This **must** be protected and remain secret. Anyone who knows
the value of your :class:`~nacl.signing.SigningKey` or it's seed can
masquerade as you.
:param seed: [:class:`bytes`] Random 32-byte value (i.e. private key)
:param encoder: A class that is able to decode the seed
:ivar: verify_key: [:class:`~nacl.signing.VerifyKey`] The verify
(i.e. public) key that corresponds with this signing key.
"""
def __init__(self, seed, encoder=encoding.RawEncoder):
# Decode the seed
seed = encoder.decode(seed)
if not isinstance(seed, bytes):
raise exc.TypeError(
"SigningKey must be created from a 32 byte seed")
# Verify that our seed is the proper size
if len(seed) != nacl.bindings.crypto_sign_SEEDBYTES:
raise exc.ValueError(
"The seed must be exactly %d bytes long" %
nacl.bindings.crypto_sign_SEEDBYTES
)
public_key, secret_key = nacl.bindings.crypto_sign_seed_keypair(seed)
self._seed = seed
self._signing_key = secret_key
self.verify_key = VerifyKey(public_key)
def __bytes__(self):
return self._seed
def __hash__(self):
return hash(bytes(self))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
def __ne__(self, other):
return not (self == other)
@classmethod
def generate(cls):
"""
Generates a random :class:`~nacl.signing.SigningKey` object.
:rtype: :class:`~nacl.signing.SigningKey`
"""
return cls(
random(nacl.bindings.crypto_sign_SEEDBYTES),
encoder=encoding.RawEncoder,
)
def sign(self, message, encoder=encoding.RawEncoder):
"""
Sign a message using this key.
:param message: [:class:`bytes`] The data to be signed.
:param encoder: A class that is used to encode the signed message.
:rtype: :class:`~nacl.signing.SignedMessage`
"""
raw_signed = nacl.bindings.crypto_sign(message, self._signing_key)
crypto_sign_BYTES = nacl.bindings.crypto_sign_BYTES
signature = encoder.encode(raw_signed[:crypto_sign_BYTES])
message = encoder.encode(raw_signed[crypto_sign_BYTES:])
signed = encoder.encode(raw_signed)
return SignedMessage._from_parts(signature, message, signed)
def to_curve25519_private_key(self):
"""
Converts a :class:`~nacl.signing.SigningKey` to a
:class:`~nacl.public.PrivateKey`
:rtype: :class:`~nacl.public.PrivateKey`
"""
sk = self._signing_key
raw_private = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(sk)
return _Curve25519_PrivateKey(raw_private)