123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- # 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
- from nacl import exceptions as exc
- from nacl._sodium import ffi, lib
- from nacl.exceptions import ensure
- __all__ = ["crypto_box_keypair", "crypto_box"]
- crypto_box_SECRETKEYBYTES = lib.crypto_box_secretkeybytes()
- crypto_box_PUBLICKEYBYTES = lib.crypto_box_publickeybytes()
- crypto_box_NONCEBYTES = lib.crypto_box_noncebytes()
- crypto_box_ZEROBYTES = lib.crypto_box_zerobytes()
- crypto_box_BOXZEROBYTES = lib.crypto_box_boxzerobytes()
- crypto_box_BEFORENMBYTES = lib.crypto_box_beforenmbytes()
- def crypto_box_keypair():
- """
- Returns a randomly generated public and secret key.
- :rtype: (bytes(public_key), bytes(secret_key))
- """
- pk = ffi.new("unsigned char[]", crypto_box_PUBLICKEYBYTES)
- sk = ffi.new("unsigned char[]", crypto_box_SECRETKEYBYTES)
- rc = lib.crypto_box_keypair(pk, sk)
- ensure(rc == 0,
- 'Unexpected library error',
- raising=exc.RuntimeError)
- return (
- ffi.buffer(pk, crypto_box_PUBLICKEYBYTES)[:],
- ffi.buffer(sk, crypto_box_SECRETKEYBYTES)[:],
- )
- def crypto_box(message, nonce, pk, sk):
- """
- Encrypts and returns a message ``message`` using the secret key ``sk``,
- public key ``pk``, and the nonce ``nonce``.
- :param message: bytes
- :param nonce: bytes
- :param pk: bytes
- :param sk: bytes
- :rtype: bytes
- """
- if len(nonce) != crypto_box_NONCEBYTES:
- raise exc.ValueError("Invalid nonce size")
- if len(pk) != crypto_box_PUBLICKEYBYTES:
- raise exc.ValueError("Invalid public key")
- if len(sk) != crypto_box_SECRETKEYBYTES:
- raise exc.ValueError("Invalid secret key")
- padded = (b"\x00" * crypto_box_ZEROBYTES) + message
- ciphertext = ffi.new("unsigned char[]", len(padded))
- rc = lib.crypto_box(ciphertext, padded, len(padded), nonce, pk, sk)
- ensure(rc == 0,
- 'Unexpected library error',
- raising=exc.RuntimeError)
- return ffi.buffer(ciphertext, len(padded))[crypto_box_BOXZEROBYTES:]
- def crypto_box_open(ciphertext, nonce, pk, sk):
- """
- Decrypts and returns an encrypted message ``ciphertext``, using the secret
- key ``sk``, public key ``pk``, and the nonce ``nonce``.
- :param ciphertext: bytes
- :param nonce: bytes
- :param pk: bytes
- :param sk: bytes
- :rtype: bytes
- """
- if len(nonce) != crypto_box_NONCEBYTES:
- raise exc.ValueError("Invalid nonce size")
- if len(pk) != crypto_box_PUBLICKEYBYTES:
- raise exc.ValueError("Invalid public key")
- if len(sk) != crypto_box_SECRETKEYBYTES:
- raise exc.ValueError("Invalid secret key")
- padded = (b"\x00" * crypto_box_BOXZEROBYTES) + ciphertext
- plaintext = ffi.new("unsigned char[]", len(padded))
- res = lib.crypto_box_open(plaintext, padded, len(padded), nonce, pk, sk)
- ensure(res == 0, "An error occurred trying to decrypt the message",
- raising=exc.CryptoError)
- return ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:]
- def crypto_box_beforenm(pk, sk):
- """
- Computes and returns the shared key for the public key ``pk`` and the
- secret key ``sk``. This can be used to speed up operations where the same
- set of keys is going to be used multiple times.
- :param pk: bytes
- :param sk: bytes
- :rtype: bytes
- """
- if len(pk) != crypto_box_PUBLICKEYBYTES:
- raise exc.ValueError("Invalid public key")
- if len(sk) != crypto_box_SECRETKEYBYTES:
- raise exc.ValueError("Invalid secret key")
- k = ffi.new("unsigned char[]", crypto_box_BEFORENMBYTES)
- rc = lib.crypto_box_beforenm(k, pk, sk)
- ensure(rc == 0,
- 'Unexpected library error',
- raising=exc.RuntimeError)
- return ffi.buffer(k, crypto_box_BEFORENMBYTES)[:]
- def crypto_box_afternm(message, nonce, k):
- """
- Encrypts and returns the message ``message`` using the shared key ``k`` and
- the nonce ``nonce``.
- :param message: bytes
- :param nonce: bytes
- :param k: bytes
- :rtype: bytes
- """
- if len(nonce) != crypto_box_NONCEBYTES:
- raise exc.ValueError("Invalid nonce")
- if len(k) != crypto_box_BEFORENMBYTES:
- raise exc.ValueError("Invalid shared key")
- padded = b"\x00" * crypto_box_ZEROBYTES + message
- ciphertext = ffi.new("unsigned char[]", len(padded))
- rc = lib.crypto_box_afternm(ciphertext, padded, len(padded), nonce, k)
- ensure(rc == 0,
- 'Unexpected library error',
- raising=exc.RuntimeError)
- return ffi.buffer(ciphertext, len(padded))[crypto_box_BOXZEROBYTES:]
- def crypto_box_open_afternm(ciphertext, nonce, k):
- """
- Decrypts and returns the encrypted message ``ciphertext``, using the shared
- key ``k`` and the nonce ``nonce``.
- :param ciphertext: bytes
- :param nonce: bytes
- :param k: bytes
- :rtype: bytes
- """
- if len(nonce) != crypto_box_NONCEBYTES:
- raise exc.ValueError("Invalid nonce")
- if len(k) != crypto_box_BEFORENMBYTES:
- raise exc.ValueError("Invalid shared key")
- padded = (b"\x00" * crypto_box_BOXZEROBYTES) + ciphertext
- plaintext = ffi.new("unsigned char[]", len(padded))
- res = lib.crypto_box_open_afternm(
- plaintext, padded, len(padded), nonce, k)
- ensure(res == 0, "An error occurred trying to decrypt the message",
- raising=exc.CryptoError)
- return ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:]
|