3 # Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
5 # Contact: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License
21 Python3 bindings for YACA.
23 Usage is almost the same as in the C API. All the functions that made
24 sense in Python were implemented. Memory allocations and functions for
25 getting length of the buffers were ommited as all those things are
26 handled automatically for both input and output.
28 All the parameters for strings/data expect python's bytes type. All
29 the parameters are named the same as in the C API and their meaning is
32 The major exception being encrypt/decrypt update where second
33 parameter can have 2 meanings. This is only used for CCM_AAD. See
36 Some parameters now have default values for ease of use.
38 For details please refer to the C API doxygen documentation.
40 For examples see tests/examples in yaca.tests module.
44 import ctypes as _ctypes
46 from yaca.error import *
51 _lib = yaca.library.get_yaca()
57 def _get_char_param_nullify_if_zero(param):
58 return None if len(param) == 0 else param
61 def _context_get_output_length(ctx, input_length):
62 output_length = _ctypes.c_size_t()
63 _lib.yaca_context_get_output_length(ctx,
65 _ctypes.byref(output_length))
66 return output_length.value
72 def __init__(self, ptr):
73 if not isinstance(ptr, _ctypes.c_void_p):
74 raise TypeError('Invalid type')
75 self._as_parameter_ = ptr
78 _lib.yaca_context_destroy(self._as_parameter_)
82 def __init__(self, ptr):
83 if not isinstance(ptr, _ctypes.c_void_p):
84 raise TypeError('Invalid type')
85 self._as_parameter_ = ptr
88 _lib.yaca_key_destroy(self._as_parameter_)
91 if self._as_parameter_.value is None:
92 return '<yaca.Key: KEY_NULL>'
93 return '<yaca.Key: ' + str(self.get_type()) + ', ' + \
94 str(self.get_bit_length()) + ' bits at ' + str(hex(id(self))) + '>'
97 return key_get_type(self)
99 def get_bit_length(self):
100 return key_get_bit_length(self)
103 KEY_NULL = Key(_ctypes.c_void_p())
109 class KEY_FORMAT(_enum.Enum):
115 class KEY_FILE_FORMAT(_enum.Enum):
123 class KEY_TYPE(_enum.Enum):
140 class KEY_BIT_LENGTH(_enum.IntEnum):
158 class KEY_BIT_LENGTH_EC(_enum.IntEnum):
159 PRIME192V1 = 0x300000C0
160 PRIME256V1 = 0x30000100
161 SECP256K1 = 0x31200100
162 SECP384R1 = 0x31100180
163 SECP521R1 = 0x31100209
166 KEY_LENGTH_DH_GENERATOR_2 = 0x10000000
167 KEY_LENGTH_DH_GENERATOR_5 = 0x11000000
171 class KEY_BIT_LENGTH_DH_RFC(_enum.IntEnum):
172 L1024_160 = 0x20000400
173 L2048_224 = 0x21000800
174 L2048_256 = 0x22000800
178 class DIGEST_ALGORITHM(_enum.Enum):
188 class ENCRYPT_ALGORITHM(_enum.Enum):
191 UNSAFE_TRIPPLE_DES_2TDEA = 2
192 TRIPPLE_DES_3TDEA = 3
199 class BLOCK_CIPHER_MODE(_enum.Enum):
214 class PROPERTY(_enum.Enum):
222 RC2_EFFECTIVE_KEY_BITS = 7
226 class PADDING(_enum.Enum):
237 class KDF(_enum.Enum):
242 # Implementation crypto
245 """Initializes the library. Must be called before any other crypto
246 function. Should be called once in each thread that uses yaca."""
247 _lib.yaca_initialize()
251 """Cleans up the library.
252 Must be called before exiting the thread that called yaca_initialize()."""
256 def memcmp(first, second, length):
257 """Safely compares first length bytes of two buffers."""
258 l = _ctypes.c_size_t(length)
259 return _lib.yaca_memcmp(first, second, l)
262 def random_bytes(length):
263 """Generates random data."""
264 data = _ctypes.create_string_buffer(length)
265 _lib.yaca_randomize_bytes(data, length)
269 def context_set_property(ctx, prop, prop_val):
270 """Sets the non-standard context properties.
271 Can only be called on an initialized context."""
272 if prop == PROPERTY.PADDING:
273 value = _ctypes.c_int(prop_val.value)
274 value_length = _ctypes.sizeof(value)
275 _lib.yaca_context_set_property(ctx,
277 _ctypes.byref(value),
279 elif (prop == PROPERTY.GCM_AAD) or (prop == PROPERTY.CCM_AAD) or \
280 (prop == PROPERTY.GCM_TAG) or (prop == PROPERTY.CCM_TAG):
282 value_length = len(prop_val)
283 _lib.yaca_context_set_property(ctx, prop.value,
285 elif (prop == PROPERTY.GCM_TAG_LEN) or (prop == PROPERTY.CCM_TAG_LEN) or \
286 (prop == PROPERTY.RC2_EFFECTIVE_KEY_BITS):
287 value = _ctypes.c_size_t(prop_val)
288 value_length = _ctypes.sizeof(value)
289 _lib.yaca_context_set_property(
290 ctx, prop.value, _ctypes.byref(value), value_length)
292 raise InvalidParameterError('Wrong property passed')
295 def context_get_property(ctx, prop):
296 """Returns the non-standard context properties.
297 Can only be called on an initialized context."""
298 value = _ctypes.c_void_p()
299 value_length = _ctypes.c_size_t()
300 _lib.yaca_context_get_property(ctx, prop.value, _ctypes.byref(value),
301 _ctypes.byref(value_length))
302 if prop == PROPERTY.PADDING:
303 value_cast = _ctypes.cast(value, _ctypes.POINTER(_ctypes.c_int))
304 value_proper = value_cast.contents.value
305 assert value_length.value == _ctypes.sizeof(value_cast.contents)
306 elif (prop == PROPERTY.GCM_AAD) or (prop == PROPERTY.CCM_AAD) or \
307 (prop == PROPERTY.GCM_TAG) or (prop == PROPERTY.CCM_TAG):
308 value_cast = _ctypes.cast(value, _ctypes.POINTER(_ctypes.c_char))
309 value_proper = value_cast[:value_length.value]
310 assert value_length.value == len(value_proper)
311 elif (prop == PROPERTY.GCM_TAG_LEN) or \
312 (prop == PROPERTY.CCM_TAG_LEN) or \
313 (prop == PROPERTY.RC2_EFFECTIVE_KEY_BITS):
314 value_cast = _ctypes.cast(value, _ctypes.POINTER(_ctypes.c_size_t))
315 value_proper = value_cast.contents.value
316 assert value_length.value == _ctypes.sizeof(value_cast.contents)
318 raise InvalidParameterError('Wrong property passed')
319 _lib.yaca_free(value)
325 def key_get_type(key):
326 """Gets key's type"""
327 key_type = _ctypes.c_int()
328 _lib.yaca_key_get_type(key, _ctypes.byref(key_type))
329 return KEY_TYPE(key_type.value)
332 def key_get_bit_length(key):
333 """Gets key's length (in bits)."""
334 key_bit_length = _ctypes.c_size_t()
335 _lib.yaca_key_get_bit_length(key, _ctypes.byref(key_bit_length))
336 return key_bit_length.value
339 def key_import(data, key_type=KEY_TYPE.SYMMETRIC, password=b''):
340 """Imports a key or key generation parameters."""
341 key = _ctypes.c_void_p()
342 _lib.yaca_key_import(key_type.value, _ctypes.c_char_p(password),
343 data, len(data), _ctypes.byref(key))
347 def key_export(key, key_file_fmt=KEY_FILE_FORMAT.BASE64,
348 key_fmt=KEY_FORMAT.DEFAULT, password=b''):
349 """Exports a key or key generation parameters to arbitrary format."""
350 data = _ctypes.POINTER(_ctypes.c_char)()
351 data_length = _ctypes.c_size_t()
352 _lib.yaca_key_export(key, key_fmt.value, key_file_fmt.value,
353 _ctypes.c_char_p(password), _ctypes.byref(data),
354 _ctypes.byref(data_length))
355 data_bytes = data[:data_length.value]
360 def key_generate(key_type=KEY_TYPE.SYMMETRIC,
361 key_bit_length=KEY_BIT_LENGTH.L256BIT):
362 """Generates a secure key or key generation parameters
363 (or an Initialization Vector)."""
364 key = _ctypes.c_void_p()
365 _lib.yaca_key_generate(key_type.value, key_bit_length,
370 def key_generate_from_parameters(params):
371 """Generates a secure private asymmetric key from parameters."""
372 prv_key = _ctypes.c_void_p()
373 _lib.yaca_key_generate_from_parameters(params,
374 _ctypes.byref(prv_key))
378 def key_extract_public(prv_key):
379 """Extracts public key from a private one."""
380 pub_key = _ctypes.c_void_p()
381 _lib.yaca_key_extract_public(prv_key, _ctypes.byref(pub_key))
385 def key_extract_parameters(key):
386 """Extracts parameters from a private or a public key."""
387 params = _ctypes.c_void_p()
388 _lib.yaca_key_extract_parameters(key, _ctypes.byref(params))
392 def key_derive_dh(prv_key, pub_key):
393 """Derives a shared secret using Diffie-Helmann or EC Diffie-Helmann
394 key exchange protocol."""
395 secret = _ctypes.POINTER(_ctypes.c_char)()
396 secret_length = _ctypes.c_size_t()
397 _lib.yaca_key_derive_dh(prv_key, pub_key, _ctypes.byref(secret),
398 _ctypes.byref(secret_length))
399 secret_bytes = secret[:secret_length.value]
400 _lib.yaca_free(secret)
404 def key_derive_kdf(secret, key_material_length, info=b'',
405 kdf=KDF.X942, digest_algo=DIGEST_ALGORITHM.SHA256):
406 """Derives a key material from shared secret."""
407 info_param = _get_char_param_nullify_if_zero(info)
408 key_material = _ctypes.POINTER(_ctypes.c_char)()
409 _lib.yaca_key_derive_kdf(kdf.value, digest_algo.value,
411 info_param, len(info), key_material_length,
412 _ctypes.byref(key_material))
413 key_material_bytes = key_material[:key_material_length]
414 _lib.yaca_free(key_material)
415 return key_material_bytes
418 def key_derive_pbkdf2(password, key_bit_length=KEY_BIT_LENGTH.L256BIT,
419 salt=b'', digest_algo=DIGEST_ALGORITHM.SHA256,
421 """Derives a key from user password (PKCS #5 a.k.a. pbkdf2 algorithm)."""
422 salt_param = _get_char_param_nullify_if_zero(salt)
423 key = _ctypes.c_void_p()
424 _lib.yaca_key_derive_pbkdf2(_ctypes.c_char_p(password), salt_param,
425 len(salt), iterations, digest_algo.value,
426 key_bit_length, _ctypes.byref(key))
430 # Implementation simple
432 def simple_encrypt(sym_key, plaintext, encrypt_algo=ENCRYPT_ALGORITHM.AES,
433 bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
434 """Encrypts data using a symmetric cipher."""
435 plaintext_param = _get_char_param_nullify_if_zero(plaintext)
436 ciphertext = _ctypes.POINTER(_ctypes.c_char)()
437 ciphertext_length = _ctypes.c_size_t()
438 _lib.yaca_simple_encrypt(encrypt_algo.value, bcm.value, sym_key, iv,
439 plaintext_param, len(plaintext),
440 _ctypes.byref(ciphertext),
441 _ctypes.byref(ciphertext_length))
442 ciphertext_bytes = ciphertext[:ciphertext_length.value]
443 _lib.yaca_free(ciphertext)
444 return ciphertext_bytes
447 def simple_decrypt(sym_key, ciphertext, encrypt_algo=ENCRYPT_ALGORITHM.AES,
448 bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
449 """Decrypts data using a symmetric cipher."""
450 ciphertext_param = _get_char_param_nullify_if_zero(ciphertext)
451 plaintext = _ctypes.POINTER(_ctypes.c_char)()
452 plaintext_length = _ctypes.c_size_t()
453 _lib.yaca_simple_decrypt(encrypt_algo.value, bcm.value, sym_key, iv,
454 ciphertext_param, len(ciphertext),
455 _ctypes.byref(plaintext),
456 _ctypes.byref(plaintext_length))
457 plaintext_bytes = plaintext[:plaintext_length.value]
458 _lib.yaca_free(plaintext)
459 return plaintext_bytes
462 def simple_calculate_digest(message, digest_algo=DIGEST_ALGORITHM.SHA256):
463 """Calculates a digest of a message."""
464 message_param = _get_char_param_nullify_if_zero(message)
465 digest = _ctypes.POINTER(_ctypes.c_char)()
466 digest_length = _ctypes.c_size_t()
467 _lib.yaca_simple_calculate_digest(digest_algo.value, message_param,
469 _ctypes.byref(digest),
470 _ctypes.byref(digest_length))
471 digest_bytes = digest[:digest_length.value]
472 _lib.yaca_free(digest)
476 def simple_calculate_signature(prv_key, message,
477 digest_algo=DIGEST_ALGORITHM.SHA256):
478 """Creates a signature using asymmetric private key."""
479 message_param = _get_char_param_nullify_if_zero(message)
480 signature = _ctypes.POINTER(_ctypes.c_char)()
481 signature_length = _ctypes.c_size_t()
482 _lib.yaca_simple_calculate_signature(digest_algo.value, prv_key,
483 message_param, len(message),
484 _ctypes.byref(signature),
485 _ctypes.byref(signature_length))
486 signature_bytes = signature[:signature_length.value]
487 _lib.yaca_free(signature)
488 return signature_bytes
491 def simple_verify_signature(pub_key, message, signature,
492 digest_algo=DIGEST_ALGORITHM.SHA256):
493 """Verifies a signature using asymmetric public key."""
494 return _lib.yaca_simple_verify_signature(digest_algo.value, pub_key,
495 message, len(message),
496 signature, len(signature))
499 def simple_calculate_hmac(sym_key, message,
500 digest_algo=DIGEST_ALGORITHM.SHA256):
501 """Calculates a HMAC of given message using symmetric key."""
502 message_param = _get_char_param_nullify_if_zero(message)
503 mac = _ctypes.POINTER(_ctypes.c_char)()
504 mac_length = _ctypes.c_size_t()
505 _lib.yaca_simple_calculate_hmac(digest_algo.value, sym_key,
506 message_param, len(message),
508 _ctypes.byref(mac_length))
509 mac_bytes = mac[:mac_length.value]
514 def simple_calculate_cmac(sym_key, message,
515 encrypt_algo=ENCRYPT_ALGORITHM.AES):
516 """Calculates a CMAC of given message using symmetric key."""
517 message_param = _get_char_param_nullify_if_zero(message)
518 mac = _ctypes.POINTER(_ctypes.c_char)()
519 mac_length = _ctypes.c_size_t()
520 _lib.yaca_simple_calculate_cmac(encrypt_algo.value, sym_key,
521 message_param, len(message),
523 _ctypes.byref(mac_length))
524 mac_bytes = mac[:mac_length.value]
529 # Implementation digest
531 def digest_initialize(digest_algo=DIGEST_ALGORITHM.SHA256):
532 """Initializes a digest context."""
533 ctx = _ctypes.c_void_p()
534 _lib.yaca_digest_initialize(_ctypes.byref(ctx), digest_algo.value)
538 def digest_update(ctx, message):
539 """Feeds the message into the message digest algorithm."""
540 _lib.yaca_digest_update(ctx, message, len(message))
543 def digest_finalize(ctx):
544 """Calculates the final digest."""
545 output_length = _context_get_output_length(ctx, 0)
546 digest = _ctypes.create_string_buffer(output_length)
547 digest_length = _ctypes.c_size_t()
548 _lib.yaca_digest_finalize(ctx, digest, _ctypes.byref(digest_length))
549 return bytes(digest[:digest_length.value])
552 # Implementation encrypt
554 def encrypt_get_iv_bit_length(encrypt_algo, bcm, key_bin_length):
555 """Returns the recommended/default length of the Initialization Vector
556 for a given encryption configuration."""
557 iv_bit_length = _ctypes.c_size_t()
558 _lib.yaca_encrypt_get_iv_bit_length(encrypt_algo.value, bcm.value,
560 _ctypes.byref(iv_bit_length))
561 return iv_bit_length.value
564 def encrypt_initialize(sym_key, encrypt_algo=ENCRYPT_ALGORITHM.AES,
565 bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
566 """Initializes an encryption context."""
567 ctx = _ctypes.c_void_p()
568 _lib.yaca_encrypt_initialize(_ctypes.byref(ctx), encrypt_algo.value,
569 bcm.value, sym_key, iv)
573 def encrypt_update(ctx, plaintext):
574 """Encrypts chunk of the data.
575 Alternatively plaintext can be the total length of the input (int).
576 This is used for CCM_AAD."""
577 if isinstance(plaintext, int): # the case of using AAD in CCM
578 _lib.yaca_encrypt_update(ctx, None, plaintext, None,
579 _ctypes.byref(_ctypes.c_size_t()))
582 output_length = _context_get_output_length(ctx, len(plaintext))
583 ciphertext = _ctypes.create_string_buffer(output_length)
584 ciphertext_length = _ctypes.c_size_t()
585 _lib.yaca_encrypt_update(ctx, plaintext, len(plaintext),
586 ciphertext, _ctypes.byref(ciphertext_length))
587 return bytes(ciphertext[:ciphertext_length.value])
590 def encrypt_finalize(ctx):
591 """Encrypts the final chunk of the data."""
592 output_length = _context_get_output_length(ctx, 0)
593 ciphertext = _ctypes.create_string_buffer(output_length)
594 ciphertext_length = _ctypes.c_size_t()
595 _lib.yaca_encrypt_finalize(ctx, ciphertext,
596 _ctypes.byref(ciphertext_length))
597 return bytes(ciphertext[:ciphertext_length.value])
600 def decrypt_initialize(sym_key, encrypt_algo=ENCRYPT_ALGORITHM.AES,
601 bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
602 """Initializes an decryption context."""
603 ctx = _ctypes.c_void_p()
604 _lib.yaca_decrypt_initialize(_ctypes.byref(ctx), encrypt_algo.value,
605 bcm.value, sym_key, iv)
609 def decrypt_update(ctx, ciphertext):
610 """Decrypts chunk of the data.
611 Alternatively ciphertext can be the total length of the input (int).
612 This is used for CCM_AAD."""
613 if isinstance(ciphertext, int): # the case of using AAD in CCM
614 _lib.yaca_decrypt_update(ctx, None, ciphertext, None,
615 _ctypes.byref(_ctypes.c_size_t()))
618 output_length = _context_get_output_length(ctx, len(ciphertext))
619 plaintext = _ctypes.create_string_buffer(output_length)
620 plaintext_length = _ctypes.c_size_t()
621 _lib.yaca_decrypt_update(ctx, ciphertext, len(ciphertext),
622 plaintext, _ctypes.byref(plaintext_length))
623 return bytes(plaintext[:plaintext_length.value])
626 def decrypt_finalize(ctx):
627 """Encrypts the final chunk of the data."""
628 output_length = _context_get_output_length(ctx, 0)
629 plaintext = _ctypes.create_string_buffer(output_length)
630 plaintext_length = _ctypes.c_size_t()
631 _lib.yaca_decrypt_finalize(ctx, plaintext,
632 _ctypes.byref(plaintext_length))
633 return bytes(plaintext[:plaintext_length.value])
636 # Implementation sign
638 def sign_initialize(prv_key, digest_algo=DIGEST_ALGORITHM.SHA256):
639 """Initializes a signature context for asymmetric signatures."""
640 ctx = _ctypes.c_void_p()
641 _lib.yaca_sign_initialize(_ctypes.byref(ctx), digest_algo.value,
646 def sign_initialize_hmac(sym_key, digest_algo=DIGEST_ALGORITHM.SHA256):
647 """Initializes a signature context for HMAC."""
648 ctx = _ctypes.c_void_p()
649 _lib.yaca_sign_initialize_hmac(_ctypes.byref(ctx),
650 digest_algo.value, sym_key)
654 def sign_initialize_cmac(sym_key, encrypt_algo=ENCRYPT_ALGORITHM.AES):
655 """Initializes a signature context for CMAC."""
656 ctx = _ctypes.c_void_p()
657 _lib.yaca_sign_initialize_cmac(_ctypes.byref(ctx),
658 encrypt_algo.value, sym_key)
662 def sign_update(ctx, message):
663 """Feeds the message into the digital signature or MAC algorithm."""
664 _lib.yaca_sign_update(ctx, message, len(message))
667 def sign_finalize(ctx):
668 """Calculates the final signature or MAC."""
669 output_length = _context_get_output_length(ctx, 0)
670 signature = _ctypes.create_string_buffer(output_length)
671 signature_len = _ctypes.c_size_t()
672 _lib.yaca_sign_finalize(ctx, signature, _ctypes.byref(signature_len))
673 return bytes(signature[:signature_len.value])
676 def verify_initialize(pub_key, digest_algo=DIGEST_ALGORITHM.SHA256):
677 """Initializes a signature verification context for asymmetric signatures.
679 ctx = _ctypes.c_void_p()
680 _lib.yaca_verify_initialize(_ctypes.byref(ctx), digest_algo.value,
685 def verify_update(ctx, message):
686 """Feeds the message into the digital signature verification algorithm."""
687 _lib.yaca_verify_update(ctx, message, len(message))
690 def verify_finalize(ctx, signature):
691 """Performs the verification."""
692 return _lib.yaca_verify_finalize(ctx, signature, len(signature))
695 # Implementation seal
697 def seal_initialize(pub_key, sym_key_bit_length=KEY_BIT_LENGTH.L256BIT,
698 encrypt_algo=ENCRYPT_ALGORITHM.AES,
699 bcm=BLOCK_CIPHER_MODE.ECB):
700 ctx = _ctypes.c_void_p()
701 sym_key = _ctypes.c_void_p()
702 iv = _ctypes.c_void_p()
703 _lib.yaca_seal_initialize(_ctypes.byref(ctx), pub_key,
704 encrypt_algo.value, bcm.value,
705 sym_key_bit_length, _ctypes.byref(sym_key),
707 return Context(ctx), Key(sym_key), Key(iv)
710 def seal_update(ctx, plaintext):
711 """Encrypts piece of the data."""
712 output_length = _context_get_output_length(ctx, len(plaintext))
713 ciphertext = _ctypes.create_string_buffer(output_length)
714 ciphertext_length = _ctypes.c_size_t()
715 _lib.yaca_seal_update(ctx, plaintext, len(plaintext),
716 ciphertext, _ctypes.byref(ciphertext_length))
717 return bytes(ciphertext[:ciphertext_length.value])
720 def seal_finalize(ctx):
721 """Encrypts the final piece of the data."""
722 output_length = _context_get_output_length(ctx, 0)
723 ciphertext = _ctypes.create_string_buffer(output_length)
724 ciphertext_length = _ctypes.c_size_t()
725 _lib.yaca_seal_finalize(ctx, ciphertext,
726 _ctypes.byref(ciphertext_length))
727 return bytes(ciphertext[:ciphertext_length.value])
730 def open_initialize(prv_key, sym_key, iv=KEY_NULL,
731 sym_key_bit_length=KEY_BIT_LENGTH.L256BIT,
732 encrypt_algo=ENCRYPT_ALGORITHM.AES,
733 bcm=BLOCK_CIPHER_MODE.ECB):
734 """Initializes an asymmetric decryption context."""
735 ctx = _ctypes.c_void_p()
736 _lib.yaca_open_initialize(_ctypes.byref(ctx), prv_key,
737 encrypt_algo.value, bcm.value,
738 sym_key_bit_length, sym_key, iv)
742 def open_update(ctx, ciphertext):
743 """Decrypts piece of the data."""
744 output_length = _context_get_output_length(ctx, len(ciphertext))
745 plaintext = _ctypes.create_string_buffer(output_length)
746 plaintext_length = _ctypes.c_size_t()
747 _lib.yaca_open_update(ctx, ciphertext, len(ciphertext),
748 plaintext, _ctypes.byref(plaintext_length))
749 return bytes(plaintext[:plaintext_length.value])
752 def open_finalize(ctx):
753 """Decrypts last chunk of sealed message."""
754 output_length = _context_get_output_length(ctx, 0)
755 plaintext = _ctypes.create_string_buffer(output_length)
756 plaintext_length = _ctypes.c_size_t()
757 _lib.yaca_open_finalize(ctx, plaintext,
758 _ctypes.byref(plaintext_length))
759 return bytes(plaintext[:plaintext_length.value])
764 def rsa_public_encrypt(pub_key, plaintext, padding=PADDING.PKCS1):
765 """Encrypts data using a RSA public key (low-level encrypt equivalent)."""
766 ciphertext = _ctypes.POINTER(_ctypes.c_char)()
767 ciphertext_length = _ctypes.c_size_t()
768 plaintext_param = _get_char_param_nullify_if_zero(plaintext)
769 _lib.yaca_rsa_public_encrypt(padding.value, pub_key, plaintext_param,
771 _ctypes.byref(ciphertext),
772 _ctypes.byref(ciphertext_length))
773 ciphertext_bytes = ciphertext[:ciphertext_length.value]
774 _lib.yaca_free(ciphertext)
775 return ciphertext_bytes
778 def rsa_private_decrypt(prv_key, ciphertext, padding=PADDING.PKCS1):
779 """Decrypts data using a RSA private key (low-level decrypt equivalent)."""
780 plaintext = _ctypes.POINTER(_ctypes.c_char)()
781 plaintext_length = _ctypes.c_size_t()
782 ciphertext_param = _get_char_param_nullify_if_zero(ciphertext)
783 _lib.yaca_rsa_private_decrypt(padding.value, prv_key,
784 ciphertext_param, len(ciphertext),
785 _ctypes.byref(plaintext),
786 _ctypes.byref(plaintext_length))
787 plaintext_bytes = plaintext[:plaintext_length.value]
788 _lib.yaca_free(plaintext)
789 return plaintext_bytes
792 def rsa_private_encrypt(prv_key, plaintext, padding=PADDING.PKCS1):
793 """Encrypts data using a RSA private key (low-level sign equivalent)."""
794 ciphertext = _ctypes.POINTER(_ctypes.c_char)()
795 ciphertext_length = _ctypes.c_size_t()
796 plaintext_param = _get_char_param_nullify_if_zero(plaintext)
797 _lib.yaca_rsa_private_encrypt(padding.value, prv_key,
798 plaintext_param, len(plaintext),
799 _ctypes.byref(ciphertext),
800 _ctypes.byref(ciphertext_length))
801 ciphertext_bytes = ciphertext[:ciphertext_length.value]
802 _lib.yaca_free(ciphertext)
803 return ciphertext_bytes
806 def rsa_public_decrypt(pub_key, ciphertext, padding=PADDING.PKCS1):
807 """Decrypts data using a RSA public key (low-level verify equivalent)."""
808 plaintext = _ctypes.POINTER(_ctypes.c_char)()
809 plaintext_length = _ctypes.c_size_t()
810 ciphertext_param = _get_char_param_nullify_if_zero(ciphertext)
811 _lib.yaca_rsa_public_decrypt(padding.value, pub_key,
812 ciphertext_param, len(ciphertext),
813 _ctypes.byref(plaintext),
814 _ctypes.byref(plaintext_length))
815 plaintext_bytes = plaintext[:plaintext_length.value]
816 _lib.yaca_free(plaintext)
817 return plaintext_bytes