Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symmetric keygen: high-level wrappers #561

Merged
merged 13 commits into from
Dec 11, 2019

Conversation

ilammy
Copy link
Collaborator

@ilammy ilammy commented Dec 4, 2019

Implement symmetric key generation utilities described in RFC 1 (not available publicly at the moment). This is new API introduced in #560, now distributed to high-level wrappers.

This PR contains ‘easy’ wrappers that do not require anything special and with more or less straightforward and compact implementation. I placed them in one PR in order to have fewer merge conflicts in the changelog later.

Node.js (JsThemis) and Java (Android) are hard. They will be added in their own PRs.

Language API

With exception of C++ there is only one entry point for key generation. High-level wrappers generally do not allow the user to customize key length and generate default keys (32 bytes).

Where applicable, new types are introduced along with conversion API.

C++

#include <themispp/secure_keygen.hpp>

std::vector<uint8_t> key = themispp::gen_sym_key();

// Write by reference, mostly for C++03 compatibility:
themispp::gen_sym_key(key);

Go

import "github.com/cossacklabs/themis/gothemis/keys"

key, err := keys.NewSymmetricKey() // returns keys.SymmetricKey

key.Value // access []byte slice

JavaScript (WebAssembly)

const themis = required('wasm-themis')

let key = new themis.SymmetricKey()
// inherits from Uint8Array to access key bytes

// Can also wrap existing buffers
let buffer = new Uint8Array([1, 2, 3, 4, 5, 6])
let anotherKey = new themis.SymmetricKey(buffer)

Objective-C

#import <objcthemis/objcthemis.h>

NSData *key = TSGenerateSymmetricKey();

PHP

// returns string with key bytes
$key = phpthemis_gen_sym_key();

Python

from pythemis.skeygen import GenerateSymmetricKey

# bytes for Python 3, str for Python2
key = GenerateSymmetricKey()

Ruby

require 'rbthemis'

# returns byte string
key = Themis::gen_sym_key()

Rust

use themis::keys::SymmetricKey;

let key = SymmetricKey::new();
// implements AsRef<[u8]> to access key bytes

// Can also wrap existing buffers
let another_key = SymmetricKey::from_slice(&[1, 2, 3, 4])?;

Swift

import Themis

let key: Data? = TSGenerateSymmetricKey();

Checklist

  • Change is covered by automated tests
  • Benchmark results are attached (not interesting)
  • The coding guidelines are followed
  • Public API has proper documentation
  • Example projects and code samples are updated (later)
  • Changelog is updated if needed

@ilammy ilammy added W-PHPThemis 🐘 Wrapper: PHPThemis, PHP API W-PyThemis 🐍 Wrapper: PyThemis, Python API W-RbThemis ♦️ Wrapper: RbThemis, Ruby API, Ruby gems W-GoThemis 🐹 Wrapper: GoThemis, Go API W-ThemisPP ⚔️ Wrapper: ThemisPP, C++ API W-SwiftThemis 🔶 Wrapper: SwiftThemis, Swift API W-RustThemis 🦀 Wrapper: Rust-Themis, Rust API, Cargo crates W-WasmThemis 🌐 Wrapper: WasmThemis, JavaScript API, npm packages W-ObjCThemis 🎨 Wrapper: ObjCThemis, Objective-C API labels Dec 4, 2019
@ilammy ilammy mentioned this pull request Dec 4, 2019
6 tasks
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.
Straightforward implementation. The only interestring thing is that
size_t is mapped to i32 with Emscripten, as noted in all other APIs.
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.
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.
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.
Straightforward implementation.

string_at() returns "str" with Python 2 and "bytes" with Python 3.
Straightforward implementation. Probably the most concise one :)
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.
@ilammy ilammy force-pushed the themis_gen_sym_key/wrappers branch from 0c9e696 to a00dbf0 Compare December 6, 2019 09:16
@ilammy ilammy marked this pull request as ready for review December 6, 2019 09:17
@ilammy
Copy link
Collaborator Author

ilammy commented Dec 6, 2019

I’ve rebased the changeset onto master which now has proper Core support. I’ve also added some updates in tests based on feedback in other PRs. This one is ready for review.

Resolve a warning about "this function declaration is not a prototype".
Objective-C is still C, not C++, so if a function does not take any
arguments then it should have "(void)" argument list, not "()". Latter
is considered to take any number of any arguments (for legacy reasons).
key = [NSMutableData dataWithLength:keyLength];

result = (TSErrorType) themis_gen_sym_key(key.mutableBytes, &keyLength);
if (result != TSErrorTypeSuccess) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (result != TSErrorTypeSuccess) {
if (result != TSErrorTypeSuccess) {
[key resetBytesInRange:NSMakeRange(0, [key length])];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[key resetBytesInRange:NSMakeRange(0, [key length])];

I'd think this will be excessive when these suggestion is implemented in Themis Core. It will ensure that if themis_gen_sym_key() fails then output buffer does not contain anything useful or sensitive. That way we will not need to add additional wiping to every single wrapper individually.

Copy link
Contributor

@vixentael vixentael Dec 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree.

another reason I suggested it for iOS only – I don't know how to zeroing bytes in every other language :D

@vixentael
Copy link
Contributor

That's a lot of going on here!

@ilammy
Copy link
Collaborator Author

ilammy commented Dec 6, 2019

That's a lot of going on here!

I have a faint feeling that this PR should have been nine separate PRs...

Also, @vixentael, by chance, do you have a guess why Bitrise build keeps failing? Because it's certainly fine on the master branch, the changes do not seem to have anything to do with OpenSSL includes, not to say that the framework and tests build fine on my machine.

public function testKeyGeneration() {
$defaultLength = 32;
$key = phpthemis_gen_sym_key();
$this->assertEquals(strlen($key), $defaultLength);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be better if for php we will have more checks, like in themis core, where we check that several calls of function return different keys. because php has a more complicated wrapper and own memory management.

Just like with JsThemis that has nontrivial wrapper, let's make sure
that key generation returns distinct objects for every call and we
don't do anything silly in the implementation.
@ilammy
Copy link
Collaborator Author

ilammy commented Dec 6, 2019

why Bitrise build keeps failing

I have a guess:

# example should work with head
pod 'themis', :git => "https://github.com/cossacklabs/themis.git"

This pulls in ObjCThemis code from master branch, not from a pull request, that's probably why the tests don't see the new API, and... that causes an error about <openssl/crypto.h> being not found to be displayed? Weird but possible. It's Apple after all, you should think different™

For local testing I have always been using an edited Podfile that refers to this branch. However, if I use it without changes then the errors are different, like more appropriate:

Use of unresolved identifier 'TSGenerateSymmetricKey'

@ilammy
Copy link
Collaborator Author

ilammy commented Dec 6, 2019

Oh, I get it now. Carthage build fails because carthage bootstrap step did not run as it’s not marked “run if previous steps fail”, and that causes an error with OpenSSL: of course we don’t have headers if the dependencies are not fetched. CocoaPods build fails for the reason I described above.

I’ve tweaked Bitrise build steps to avoid these issues:

  1. Added a new Hack Podfile to use PR branch step before pod install so that we install the code from the pull request, not from the master branch.
  2. Marked Carthage bootstrap step to “Run if previous Step failed”.

Let’s see if this is all we need.

@vixentael
Copy link
Contributor

Looks like you fixed a problem with Bitrise

Copy link
Contributor

@vixentael vixentael left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge 'em all!

@ilammy ilammy merged commit 3ff3cca into cossacklabs:master Dec 11, 2019
@ilammy ilammy deleted the themis_gen_sym_key/wrappers branch December 11, 2019 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
W-GoThemis 🐹 Wrapper: GoThemis, Go API W-ObjCThemis 🎨 Wrapper: ObjCThemis, Objective-C API W-PHPThemis 🐘 Wrapper: PHPThemis, PHP API W-PyThemis 🐍 Wrapper: PyThemis, Python API W-RbThemis ♦️ Wrapper: RbThemis, Ruby API, Ruby gems W-RustThemis 🦀 Wrapper: Rust-Themis, Rust API, Cargo crates W-SwiftThemis 🔶 Wrapper: SwiftThemis, Swift API W-ThemisPP ⚔️ Wrapper: ThemisPP, C++ API W-WasmThemis 🌐 Wrapper: WasmThemis, JavaScript API, npm packages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants