Skip to content

Commit

Permalink
Proof of concept that we can use bytes or buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeboers committed Nov 14, 2013
1 parent 52c7ba8 commit 2234098
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 4 deletions.
4 changes: 4 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
- Anything which takes bytes should be able to take a bytearray or memoryview
as well. See: http://docs.cython.org/src/userguide/memoryviews.html


- expose all the pkcs5/oaep/pss padding functions
- passing `hash=None` to sign/verify will cause it to assume it was passed a digest

Expand Down
22 changes: 18 additions & 4 deletions src/cipher.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ cdef class Cipher(Descriptor):
len(header)))

% for type in 'encrypt decrypt'.split():
cpdef ${type}(self, bytes input):
cpdef ${type}(self, input_):
"""${type}(input)
${type.capitalize()} a string.
Expand All @@ -365,17 +365,31 @@ cdef class Cipher(Descriptor):
% endif
"""

# Accept something that can be coerced into a writable buffer, or
# directly into a pointer.
# TODO: abstract this into a utility somewhere for further use.
cdef unsigned char[::1] input_view
cdef unsigned char *input_ptr
cdef int length
length = len(input)
try:
input_view = input_
length = input_view.shape[0] * input_view.itemsize
input_ptr = &input_view[0]
except BufferError:
input_ptr = input_
length = len(input_)

# We need to make sure we have a brand new string as it is going to be
# modified. The input will not be, so we can use the python one.
output = PyBytes_FromStringAndSize(NULL, length)

% for mode, i in cipher_mode_items:
${'el' if i else ''}if self.mode_i == ${i}: # ${mode}
% if mode in cipher_auth_modes:
check_for_error(${mode}_${type}(<${mode}_state*>&self.state, input, output, length))
check_for_error(${mode}_${type}(<${mode}_state*>&self.state, input_ptr, output, length))
% else:
check_for_error(${mode}_${type}(input, output, length, <symmetric_${mode}*>&self.state))
check_for_error(${mode}_${type}(input_ptr, output, length, <symmetric_${mode}*>&self.state))
% endif
% endfor
return output
Expand Down
8 changes: 8 additions & 0 deletions tests/test_cipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,11 @@ def test_api(self):
msg = b'hello, world'
enc = cipher.aes(key, iv).encrypt(msg)
self.assertEqual(cipher.aes(key, iv).decrypt(enc), msg)

def test_bytearrays(self):
key = b'0123456789abcdef'
iv = b'0' * 16
msg = bytearray(b'hello, world')
enc = cipher.aes(key, iv).encrypt(msg)
self.assertEqual(cipher.aes(key, iv).decrypt(enc), msg)

0 comments on commit 2234098

Please sign in to comment.