Skip to content
Snippets Groups Projects
Commit eaa362c1 authored by Donald Stufft's avatar Donald Stufft
Browse files

Add secret key encryption via Salsa20 + Poly1305

* Adds nacl.secret.SecretBox which represents a secret key.
* nacl.secret.SecretBox().encrypt can be used to encrypt a message
* nacl.secret.Secretbox().decrypt can be used to decrypt a message
parent 7c19e1a0
No related branches found
No related tags found
No related merge requests found
...@@ -14,7 +14,16 @@ __all__ = ["ffi", "lib"] ...@@ -14,7 +14,16 @@ __all__ = ["ffi", "lib"]
ffi = FFI() ffi = FFI()
ffi.cdef( ffi.cdef(
# pylint: disable=C0301 # Secret Key Encryption
"""
static const int crypto_secretbox_KEYBYTES;
static const int crypto_secretbox_NONCEBYTES;
static const int crypto_secretbox_ZEROBYTES;
static const int crypto_secretbox_BOXZEROBYTES;
int crypto_secretbox(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k);
int crypto_secretbox_open(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k);
"""
# Public Key Encryption - Signatures # Public Key Encryption - Signatures
""" """
...@@ -59,6 +68,8 @@ def wrap_nacl_function(func): ...@@ -59,6 +68,8 @@ def wrap_nacl_function(func):
return ret == 0 return ret == 0
return wrapper return wrapper
lib.crypto_secretbox = wrap_nacl_function(lib.crypto_secretbox)
lib.crypto_secretbox_open = wrap_nacl_function(lib.crypto_secretbox_open)
lib.crypto_sign_seed_keypair = wrap_nacl_function(lib.crypto_sign_seed_keypair) lib.crypto_sign_seed_keypair = wrap_nacl_function(lib.crypto_sign_seed_keypair)
lib.crypto_sign = wrap_nacl_function(lib.crypto_sign) lib.crypto_sign = wrap_nacl_function(lib.crypto_sign)
......
from __future__ import absolute_import
from __future__ import division
from . import six
from . import nacl, encoding
from .exceptions import CryptoError
class SecretBox(encoding.Encodable, six.StringFixer, object):
KEY_SIZE = nacl.lib.crypto_secretbox_KEYBYTES
def __init__(self, key, encoder=encoding.RawEncoder):
key = encoder.decode(key)
if len(key) != self.KEY_SIZE:
raise ValueError("The key must be exactly %s bytes long" %
nacl.lib.crypto_secretbox_KEYBYTES)
self._key = key
def __bytes__(self):
return self._key
def encrypt(self, plaintext, nonce, encoder=encoding.RawEncoder):
if len(nonce) != nacl.lib.crypto_secretbox_NONCEBYTES:
raise ValueError("The nonce must be exactly %s bytes long" %
nacl.lib.crypto_secretbox_NONCEBYTES)
padded = b"\x00" * nacl.lib.crypto_secretbox_ZEROBYTES + plaintext
ciphertext = nacl.ffi.new("unsigned char[]", len(padded))
if not nacl.lib.crypto_secretbox(
ciphertext, padded, len(padded), nonce, self._key,
):
raise CryptoError("Encryption failed")
box_zeros = nacl.lib.crypto_secretbox_BOXZEROBYTES
ciphertext = nacl.ffi.buffer(ciphertext, len(padded))[box_zeros:]
return encoder.encode(ciphertext)
def decrypt(self, ciphertext, nonce, encoder=encoding.RawEncoder):
if len(nonce) != nacl.lib.crypto_secretbox_NONCEBYTES:
raise ValueError("The nonce must be exactly %s bytes long" %
nacl.lib.crypto_secretbox_NONCEBYTES)
ciphertext = encoder.decode(ciphertext)
padded = b"\x00" * nacl.lib.crypto_secretbox_BOXZEROBYTES + ciphertext
plaintext = nacl.ffi.new("unsigned char[]", len(padded))
if not nacl.lib.crypto_secretbox_open(
plaintext, padded, len(padded), nonce, self._key,
):
raise CryptoError(
"Decryption failed. Ciphertext failed verification")
box_zeros = nacl.lib.crypto_secretbox_ZEROBYTES
plaintext = nacl.ffi.buffer(plaintext, len(padded))[box_zeros:]
return plaintext
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment