Skip to content

Commit

Permalink
Symmetric keygen: high-level wrappers (#561)
Browse files Browse the repository at this point in the history
* Symmetric keygen: ThemisPP

C++ provides both convenient and in-place key generation routines.

In-place key generation may be useful for C++03 code that does not
want to have an extra copy of std::vector when it's being returned.

ThemisPP does not provide separate types for keys, it works with
plain std::vector.

* Symmetric keygen: WasmThemis

Straightforward implementation. The only interestring thing is that
size_t is mapped to i32 with Emscripten, as noted in all other APIs.

* Symmetric keygen: GoThemis

Straightforward implementation.

GoThemis provides wrapper types for private and public keys so we
add another one with the same interface for symmetric keys.

Currently GoThemis does not return Themis error codes to Go, so CGo
code returns "bool" for simplicity and consistency.

* Symmetric keygen: ObjCThemis and SwiftThemis

Straightforward implementation. Objective-C function is automatically
bridged to Swift, we don't have to do anything for that.

Keypair generation API for ObjCThemis does not report exact errors
to the user and simply returns "nil", We do the same for symmetric
key generation for consistency.

* Symmetric keygen: PHPThemis

Straightforward implementation. PHPThemis exports its functionality
as PHP functions so just add a new one. Byte arrays are returned as
simply strings, no new types here. Just don't forget that we have
to support both PHP 5 and PHP 7 wrappers.

* Symmetric keygen: PyThemis

Straightforward implementation.

string_at() returns "str" with Python 2 and "bytes" with Python 3.

* Symmetric keygen: RbThemis

Straightforward implementation. Probably the most concise one :)

* Symmetric keygen: RustThemis

Straigtforward implementation (albeit verbose).

RustThemis has a relatively high bar for API documentation quality.
Don't let it drop and provide detailed descriptions.

themis_gen_sym_key() is added to libthemis-sys by bindgen automatically,
we don't have to remember to do that manually.
  • Loading branch information
ilammy authored Dec 11, 2019
1 parent 8fe48f5 commit 3ff3cca
Show file tree
Hide file tree
Showing 24 changed files with 577 additions and 6 deletions.
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ _Code:_

- New function `themis_gen_sym_key()` can be used to securely generate symmetric keys for Secure Cell ([#560](https://github.com/cossacklabs/themis/pull/560)).

- **C++**

- New function `themispp::gen_sym_key()` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

- **Go**

- New function `keys.NewSymmetricKey()` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

- **iOS and macOS**

- New function `TSGenerateSymmetricKey()` (available in Objective-C and Swift) can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

- **Java**

- JDK location is now detected automatically in most cases, you should not need to set JAVA_HOME or JDK_INCLUDE_PATH manually ([#551](https://github.com/cossacklabs/themis/pull/551)).
Expand All @@ -27,9 +39,26 @@ _Code:_

- New class `SymmetricKey` can be used to generate symmetric keys for Secure Cell ([#562](https://github.com/cossacklabs/themis/pull/562)).

- **PHP**

- New function `phpthemis_gen_sym_key()` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

- **Python**

- Fixed compatibility issues on 32-bit platforms ([#555](https://github.com/cossacklabs/themis/pull/555)).
- New function `skeygen.GenerateSymmetricKey()` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

- **Ruby**

- New function `Themis::gen_sym_key()` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

- **Rust**

- New object `themis::keys::SymmetricKey` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

- **WebAssembly**

- New class `SymmetricKey` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).

## [0.12.0](https://github.com/cossacklabs/themis/releases/tag/0.12.0), September 27th 2019

Expand Down
46 changes: 46 additions & 0 deletions gothemis/keys/symmetric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package keys

/*
#cgo LDFLAGS: -lthemis
#include <stdbool.h>
#include <themis/themis.h>
static bool get_sym_key_size(size_t *key_len)
{
return themis_gen_sym_key(NULL, key_len) == THEMIS_BUFFER_TOO_SMALL;
}
static bool gen_sym_key(void *key, size_t key_len)
{
return themis_gen_sym_key(key, &key_len) == THEMIS_SUCCESS;
}
*/
import "C"

import (
"unsafe"

"github.com/cossacklabs/themis/gothemis/errors"
)

// SymmetricKey stores a master key for Secure Cell.
type SymmetricKey struct {
Value []byte
}

// NewSymmetricKey generates a new random symmetric key.
func NewSymmetricKey() (*SymmetricKey, error) {
var len C.size_t
if !bool(C.get_sym_key_size(&len)) {
return nil, errors.New("Failed to get symmetric key size")
}

key := make([]byte, int(len), int(len))
if !bool(C.gen_sym_key(unsafe.Pointer(&key[0]), len)) {
return nil, errors.New("Failed to generate symmetric key")
}

return &SymmetricKey{Value: key}, nil
}
17 changes: 17 additions & 0 deletions gothemis/keys/symmetric_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package keys

import (
"testing"
)

const defaultLength = 32

func TestNewSymmetricKey(t *testing.T) {
key, err := NewSymmetricKey()
if err != nil {
t.Error(err)
}
if len(key.Value) != defaultLength {
t.Error("invalid key.Value")
}
}
9 changes: 9 additions & 0 deletions src/wrappers/themis/Obj-C/objcthemis/skeygen.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ typedef NS_ENUM(NSInteger, TSKeyGenAsymmetricAlgorithm) {

@end

/**
* Generates new symmetric master key.
*
* Securely generate a new master key suitable for Secure Cell.
*
* @returns a newly allocated key of default size.
*/
NSData* __nullable TSGenerateSymmetricKey(void);

NS_ASSUME_NONNULL_END

/** @} */
Expand Down
21 changes: 21 additions & 0 deletions src/wrappers/themis/Obj-C/objcthemis/skeygen.m
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,24 @@ - (TSErrorType)generateKeys {
}

@end

NSData* __nullable TSGenerateSymmetricKey(void)
{
TSErrorType result;
NSMutableData *key;
size_t keyLength = 0;

result = (TSErrorType) themis_gen_sym_key(NULL, &keyLength);
if (result != TSErrorTypeBufferTooSmall) {
return nil;
}

key = [NSMutableData dataWithLength:keyLength];

result = (TSErrorType) themis_gen_sym_key(key.mutableBytes, &keyLength);
if (result != TSErrorTypeSuccess) {
return nil;
}

return key;
}
22 changes: 21 additions & 1 deletion src/wrappers/themis/php/php_themis.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ static zend_function_entry php_themis_functions[] = {
PHP_FE(phpthemis_secure_message_unwrap, NULL)
PHP_FE(phpthemis_gen_rsa_key_pair, NULL)
PHP_FE(phpthemis_gen_ec_key_pair, NULL)
PHP_FE(phpthemis_gen_sym_key, NULL)
PHP_FE(phpthemis_scell_seal_encrypt, NULL)
PHP_FE(phpthemis_scell_seal_decrypt, NULL)
PHP_FE(phpthemis_scell_token_protect_encrypt,NULL)
Expand Down Expand Up @@ -397,6 +398,25 @@ PHP_FUNCTION(phpthemis_gen_ec_key_pair){
add_assoc_stringl(return_value, "public_key", public_key, public_key_length, 0);
}

PHP_FUNCTION(phpthemis_gen_sym_key){
size_t key_length;
if(themis_gen_sym_key(NULL, &key_length)!=THEMIS_BUFFER_TOO_SMALL){
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Error: themis_gen_sym_key: invalid parameters.", 0 TSRMLS_CC);
RETURN_NULL();
}
uint8_t* key=emalloc(key_length);
if(key==NULL){
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Error: themis_gen_sym_key: not enough memory.", 0 TSRMLS_CC);
RETURN_NULL();
}
if(themis_gen_sym_key(key, &key_length)!=THEMIS_SUCCESS){
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Error: themis_gen_sym_key: generation failed.", 0 TSRMLS_CC);
RETURN_NULL();
}
ZVAL_STRINGL(return_value, key, (int)key_length, 0);
return;
}

PHP_FUNCTION(phpthemis_scell_seal_encrypt){
char* key;
int key_length;
Expand Down Expand Up @@ -579,4 +599,4 @@ PHP_FUNCTION(phpthemis_scell_context_imprint_decrypt){
}
ZVAL_STRINGL(return_value, decrypted_message, (int)decrypted_message_length, 0);
return;
}
}
1 change: 1 addition & 0 deletions src/wrappers/themis/php/php_themis.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ PHP_FUNCTION(phpthemis_secure_message_unwrap);
PHP_FUNCTION(phpthemis_gen_rsa_key_pair);
PHP_FUNCTION(phpthemis_gen_ec_key_pair);

PHP_FUNCTION(phpthemis_gen_sym_key);
PHP_FUNCTION(phpthemis_scell_seal_encrypt);
PHP_FUNCTION(phpthemis_scell_seal_decrypt);
PHP_FUNCTION(phpthemis_scell_token_protect_encrypt);
Expand Down
21 changes: 20 additions & 1 deletion src/wrappers/themis/php7/php_key_generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,23 @@ ZEND_FUNCTION(phpthemis_gen_ec_key_pair){
array_init(return_value);
add_assoc_stringl(return_value, "private_key", private_key, private_key_length);
add_assoc_stringl(return_value, "public_key", public_key, public_key_length);
}
}

ZEND_FUNCTION(phpthemis_gen_sym_key){
size_t key_length;
if(themis_gen_sym_key(NULL, &key_length)!=THEMIS_BUFFER_TOO_SMALL){
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Error: themis_gen_sym_key: invalid parameters.", 0 TSRMLS_CC);
RETURN_NULL();
}
uint8_t* key=emalloc(key_length);
if(key==NULL){
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Error: themis_gen_sym_key: not enough memory.", 0 TSRMLS_CC);
RETURN_NULL();
}
if(themis_gen_sym_key(key, &key_length)!=THEMIS_SUCCESS){
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Error: themis_gen_sym_key: generation failed.", 0 TSRMLS_CC);
RETURN_NULL();
}
ZVAL_STRINGL(return_value, key, (int)key_length);
return;
}
2 changes: 2 additions & 0 deletions src/wrappers/themis/php7/php_key_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@
ZEND_FUNCTION(phpthemis_gen_rsa_key_pair);
ZEND_FUNCTION(phpthemis_gen_ec_key_pair);

ZEND_FUNCTION(phpthemis_gen_sym_key);

#endif //THEMIS_KEY_GENERATOR_H
1 change: 1 addition & 0 deletions src/wrappers/themis/php7/php_themis.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static zend_function_entry php_themis_functions[] = {
ZEND_FE(phpthemis_secure_message_unwrap, NULL)
ZEND_FE(phpthemis_gen_rsa_key_pair, NULL)
ZEND_FE(phpthemis_gen_ec_key_pair, NULL)
ZEND_FE(phpthemis_gen_sym_key, NULL)
ZEND_FE(phpthemis_scell_seal_encrypt, NULL)
ZEND_FE(phpthemis_scell_seal_decrypt, NULL)
ZEND_FE(phpthemis_scell_token_protect_encrypt, NULL)
Expand Down
15 changes: 15 additions & 0 deletions src/wrappers/themis/python/pythemis/skeygen.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,18 @@ def __init__(self, *args, **kwargs):
warnings.warn("themis_gen_key_pair is deprecated in favor of "
"GenerateKeyPair.")
super(themis_gen_key_pair, self).__init__(*args, **kwargs)


def GenerateSymmetricKey():
"""Returns a byte string with newly generated key."""
key_length = c_int(0)
res = themis.themis_gen_sym_key(None, byref(key_length))
if res != THEMIS_CODES.BUFFER_TOO_SMALL:
raise ThemisError(res, "Themis failed to get symmetric key size")

key = create_string_buffer(key_length.value)
res = themis.themis_gen_sym_key(key, byref(key_length))
if res != THEMIS_CODES.SUCCESS:
raise ThemisError(res, "Themis failed to generate symmetric key")

return string_at(key, key_length.value)
21 changes: 21 additions & 0 deletions src/wrappers/themis/ruby/lib/rbthemis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class CallbacksStruct < FFI::Struct
[:pointer, :pointer, :pointer, :pointer], :int
attach_function :themis_gen_ec_key_pair,
[:pointer, :pointer, :pointer, :pointer], :int
attach_function :themis_gen_sym_key,
[:pointer, :pointer], :int

THEMIS_KEY_INVALID = 0
THEMIS_KEY_RSA_PRIVATE = 1
Expand Down Expand Up @@ -476,6 +478,24 @@ def s_verify(peer_public_key, message)
unwrapped_message.get_bytes(0, unwrapped_message_length.read_uint)
end

def gen_sym_key
key_length = FFI::MemoryPointer.new(:uint)

res = themis_gen_sym_key(nil, key_length)
if res != BUFFER_TOO_SMALL
raise ThemisError, "failed to get symmetric key size: #{res}"
end

key = FFI::MemoryPointer.new(:char, key_length.read_uint)

res = themis_gen_sym_key(key, key_length)
if res != SUCCESS
raise ThemisError, "failed to generate symmetric key: #{res}"
end

return key.get_bytes(0, key_length.read_uint)
end

class Scell
include ThemisCommon
include ThemisImport
Expand Down Expand Up @@ -702,4 +722,5 @@ def result
module_function :Sverify
module_function :s_sign
module_function :s_verify
module_function :gen_sym_key
end
6 changes: 6 additions & 0 deletions src/wrappers/themis/rust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@

The version currently in development.

## New features

- New `SymmetricKey` objects can be used as master keys for `SecureCell`. ([#561])

[#561]: https://github.com/cossacklabs/themis/pull/561

Version 0.12.0 - 2019-09-26
===========================

Expand Down
Loading

0 comments on commit 3ff3cca

Please sign in to comment.