-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds initial Rust binding for Themis. The code comes from here, version 0.0.2: https://github.com/ilammy/rust-themis I could have transferred the whole git history, but that's too much of a bother and I don't think anybody would be interested in it that much. If you wish to read the older commit messages you can always look into the original repo. Not very convenient but that's at least something. The core repository layout is a bit different from a traditional one for Rust projects. I have moved the files into appropriate places and adapted the Cargo.toml file to that. Importantly, it now requires an `include` directive so that published crates include only Rust code. Here's the current layout of Rust code: . ├─ Cargo.toml - root Cargo.toml file ├─ docs/examples │ └─ rust - Rust wrapper examples ├─ src/wrappers/themis │ └─ rust - root of the "themis" crate │ ├─ libthemis-sys - root of the "libthemis-sys" crate │ └─ src - Rust wrapper source code └─ tests └─ rust - Rust wrapper tests The Cargo.toml file is placed in the root directory so that all usual Cargo commands work from there after a fresh checkout. They do work indeed, but the Rust binding is not integrated into the core build system. We'll improve that later. The links throughout the docs and Cargo.toml files have been updated to point to Cossack Labs repo. I have also removed TravisCI badges because Rust wrapper is going to use CircleCI just like the other bindings. I have kept the original README files. These are used when publishing on crates.io and contain Rust-specific instructions. The LICENSE files in Rust wrappers are also kept intact in accordance with item 4.a of the Apache 2.0 license. As for licensing of this contribution, I'm not a lawyer, but Apache license gives the same rights to the original licensor as well as any future contributors. That's why I did not bother updating all the boilerplate comments all over the code. They still assign copyright of Rust code to "rust-themis developers". By submitting this code to the core repository the developers agree to keep the Apache 2.0 license for it, as per item 5 of the license. There are no separate prior agreements other than that.
- Loading branch information
Showing
38 changed files
with
4,973 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
[package] | ||
name = "themis" | ||
version = "0.0.2" | ||
authors = ["rust-themis developers"] | ||
description = "High-level cryptographic services for storage and messaging" | ||
homepage = "https://www.cossacklabs.com/themis/" | ||
repository = "https://github.com/cossacklabs/themis" | ||
readme = "src/wrappers/themis/rust/README.md" | ||
keywords = ["crypto", "Themis"] | ||
categories = ["cryptography", "api-bindings"] | ||
license = "Apache-2.0" | ||
include = [ | ||
"Cargo.toml", | ||
"docs/examples/rust/**/*", | ||
"src/wrappers/themis/rust/**/*", | ||
"tests/rust/**/*", | ||
] | ||
|
||
[workspace] | ||
|
||
[lib] | ||
path = "src/wrappers/themis/rust/src/lib.rs" | ||
|
||
[[example]] | ||
name = "keygen" | ||
path = "docs/examples/rust/keygen.rs" | ||
|
||
[[example]] | ||
name = "secure_cell" | ||
path = "docs/examples/rust/secure_cell.rs" | ||
|
||
[[example]] | ||
name = "secure_compare" | ||
path = "docs/examples/rust/secure_compare.rs" | ||
|
||
[[example]] | ||
name = "secure_message_client_encrypt" | ||
path = "docs/examples/rust/secure_message_client_encrypt.rs" | ||
|
||
[[example]] | ||
name = "secure_message_client_verify" | ||
path = "docs/examples/rust/secure_message_client_verify.rs" | ||
|
||
[[example]] | ||
name = "secure_message_server" | ||
path = "docs/examples/rust/secure_message_server.rs" | ||
|
||
[[test]] | ||
name = "keys" | ||
path = "tests/rust/keys.rs" | ||
|
||
[[test]] | ||
name = "secure_cell" | ||
path = "tests/rust/secure_cell.rs" | ||
|
||
[[test]] | ||
name = "secure_comparator" | ||
path = "tests/rust/secure_comparator.rs" | ||
|
||
[[test]] | ||
name = "secure_message" | ||
path = "tests/rust/secure_message.rs" | ||
|
||
[[test]] | ||
name = "secure_session" | ||
path = "tests/rust/secure_session.rs" | ||
|
||
[dependencies] | ||
libthemis-sys = { path = "src/wrappers/themis/rust/libthemis-sys", version = "=0.0.2" } | ||
|
||
[dev-dependencies] | ||
byteorder = "1.2.7" | ||
clap = "2.32" | ||
log = "0.4.5" | ||
env_logger = "0.5.13" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
Here we have some examples of Themis usage. | ||
|
||
* [**keygen**](keygen.rs) — | ||
a tool for generating ECDSA keys (usable by other examples) | ||
* [**secure_cell**](secure_cell.rs) — | ||
simple file encryption/decryption based on Secure Cell | ||
* [**secure_compare**](secure_compare.rs) — | ||
zero-knowledge secret comparison based on Secure Comparator | ||
* <b>secure_message_*</b> — | ||
secure group chat implemented with Secure Messages | ||
* [**secure_message_server**](secure_message_server.rs) — | ||
simple relay server | ||
* [**secure_message_client_encrypt**](secure_message_client_encrypt.rs) — | ||
chat client which encrypts messages | ||
* [**secure_message_client_verify**](secure_message_client_verify.rs) — | ||
chat client which signs and verifies messages | ||
|
||
You can run the examples with Cargo like this: | ||
|
||
```console | ||
$ cargo run --example keygen -- --help | ||
keygen 0.0.1 | ||
Generating private-public ECDSA key pairs. | ||
|
||
USAGE: | ||
keygen [OPTIONS] | ||
|
||
FLAGS: | ||
-h, --help Prints help information | ||
-V, --version Prints version information | ||
|
||
OPTIONS: | ||
--private <path> Private key file (default: private.key) | ||
--public <path> Public key file (default: public.key) | ||
``` | ||
|
||
Note that the arguments are passed after `--`. | ||
|
||
|
||
## keygen | ||
|
||
This tool can be used to generate key files usable by other examples. | ||
|
||
Themis supports RSA keys for some use-cases, | ||
but most of the features expect ECDSA keys. | ||
|
||
|
||
## secure_cell | ||
|
||
This is a simple file encryption tool. | ||
It supports only seal mode of _Secure Cell_. | ||
|
||
|
||
## secure_compare | ||
|
||
This tool can be used to compare secrets over network | ||
without actually sharing them. | ||
It is made possible by _Secure Comparator_. | ||
|
||
The tool includes both the server and the client | ||
selectable via command-line. | ||
Both accept the secrets on the _standard input_ | ||
and start comparison after input is complete | ||
(use Ctrl-D in a typical terminal for this). | ||
|
||
Typical comparison session looks like this: | ||
|
||
```console | ||
$ echo "secret" | cargo run --example secure_compare -- server | ||
[+] match OK | ||
``` | ||
|
||
```console | ||
$ cargo run --example secure_compare -- client | ||
secret | ||
^D | ||
[+] match OK | ||
``` | ||
|
||
|
||
## secure_message | ||
|
||
This is a more involved example of relay chat over UDP using _Secure Messages_. | ||
It is deliberately kept simple, | ||
but the same principle can be applied to properly framed TCP transports | ||
as well as to using Tokio for async IO instead of blocking stdlib. | ||
|
||
Usually you don't need to specify any custom options, | ||
the command-line defaults are expected to work right away. | ||
But you can override the defaults for port assignment and key file locations if necessary. | ||
|
||
First you'll need to generate the keys for clients. | ||
It also may be useful to enable logging before starting the server. | ||
This example uses [`env_logger` crate][env_logger] for logging | ||
which is configurable via environment variable `RUST_LOG`. | ||
|
||
[env_logger]: https://docs.rs/env_logger/0.6.0/env_logger/ | ||
|
||
```console | ||
$ export RUST_LOG=secure_message=info | ||
$ cargo run --example keygen | ||
``` | ||
|
||
Then you can start up the server as well as some clients | ||
(in separate terminal sessions): | ||
|
||
```console | ||
$ cargo run --example secure_message_server | ||
INFO 2018-09-30T19:39:49Z: secure_message_server: listening on port 7573 | ||
INFO 2018-09-30T19:40:33Z: secure_message_server: new peer: [::1]:56375 | ||
INFO 2018-09-30T19:40:36Z: secure_message_server: new peer: [::1]:56376 | ||
``` | ||
|
||
```console | ||
$ cargo run --example secure_message_client_encrypt | ||
2: hello | ||
1: hello | ||
``` | ||
|
||
The first message from the client will introduce it to the server | ||
after which the server will relay other clients' messages to the newly joined peer. | ||
(Sorry, you'll have to manually type in nicknames at the moment.) | ||
|
||
The clients use the generated keys to secure communications. | ||
You can observe the exchange with `tcpdump`: | ||
|
||
```console | ||
$ sudo tcpdump -i any -n -X udp port 7573 | ||
tcpdump: data link type PKTAP | ||
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode | ||
listening on any, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes | ||
22:45:11.587870 IP6 ::1.56375 > ::1.7573: UDP, length 63 | ||
0x0000: 1e00 0000 6004 da0e 0047 1140 0000 0000 ....`....G.@.... | ||
0x0010: 0000 0000 0000 0000 0000 0001 0000 0000 ................ | ||
0x0020: 0000 0000 0000 0000 0000 0001 dc37 1d95 .............7.. | ||
0x0030: 0047 005a 2027 0426 3f00 0000 0001 0140 .G.Z.'.&?......@ | ||
0x0040: 0c00 0000 1000 0000 0b00 0000 9786 7d70 ..............}p | ||
0x0050: 080f 1812 8aeb 0a92 18ca 91fb 008e 355c ..............5\ | ||
0x0060: 8e6a 657b 05f1 a365 3e40 a921 50cd 9a8c .je{...e>@.!P... | ||
0x0070: 6825 9a h%. | ||
``` | ||
|
||
Some notable things about this example: | ||
|
||
* The relay server has _zero knowledge_ of the encrypted message content. | ||
* The sign/verify client does not encrypt the messages | ||
(as you may see with `tcpdump`). | ||
But it still verifies their integrity. | ||
|
||
Currently all clients are expected to use the same keys. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright 2018 (c) rust-themis developers | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#[macro_use] | ||
extern crate clap; | ||
extern crate themis; | ||
|
||
use std::fs::File; | ||
use std::io::{self, Write}; | ||
|
||
use themis::keygen::gen_ec_key_pair; | ||
|
||
fn main() { | ||
let matches = clap_app!(keygen => | ||
(version: env!("CARGO_PKG_VERSION")) | ||
(about: "Generating ECDSA key pairs.") | ||
(@arg secret: --secret [path] "Secret key file (default: secret.key)") | ||
(@arg public: --public [path] "Public key file (default: public.key)") | ||
).get_matches(); | ||
let secret_path = matches.value_of("secret").unwrap_or("secret.key"); | ||
let public_path = matches.value_of("public").unwrap_or("public.key"); | ||
|
||
let (secret_key, public_key) = gen_ec_key_pair().split(); | ||
|
||
match write_file(&secret_key, &secret_path) { | ||
Ok(_) => eprintln!("wrote secret key to {}", secret_path), | ||
Err(e) => eprintln!("failed to write secret key to {}: {}", secret_path, e), | ||
} | ||
match write_file(&public_key, &public_path) { | ||
Ok(_) => eprintln!("wrote public key to {}", public_path), | ||
Err(e) => eprintln!("failed to write public key to {}: {}", public_path, e), | ||
} | ||
} | ||
|
||
fn write_file<K: AsRef<[u8]>>(key: K, path: &str) -> io::Result<()> { | ||
let mut file = File::create(path)?; | ||
file.write_all(key.as_ref())?; | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright 2018 (c) rust-themis developers | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#[macro_use] | ||
extern crate clap; | ||
extern crate themis; | ||
|
||
use std::fs::File; | ||
use std::io::{self, Read, Write}; | ||
|
||
use themis::secure_cell::SecureCell; | ||
|
||
fn main() { | ||
let matches = clap_app!(secure_cell => | ||
(version: env!("CARGO_PKG_VERSION")) | ||
(about: "Simple encryption with Secure Cell.") | ||
(@group mode => | ||
(@arg encrypt: -e --encrypt "Encrypt the input [default]") | ||
(@arg decrypt: -d --decrypt "Decrypt the input") | ||
) | ||
(@arg password: -p --password <string> "Password to use") | ||
(@arg input: +required "Input file") | ||
(@arg output: +required "Output file") | ||
).get_matches(); | ||
|
||
let encrypt = !matches.is_present("decrypt"); | ||
let password = matches.value_of("password").unwrap(); | ||
let input_path = matches.value_of("input").unwrap(); | ||
let output_path = matches.value_of("output").unwrap(); | ||
|
||
let cell = SecureCell::with_key(&password).seal(); | ||
|
||
let input = read_file(&input_path).unwrap(); | ||
let output = if encrypt { | ||
cell.encrypt(&input).unwrap() | ||
} else { | ||
cell.decrypt(&input).unwrap() | ||
}; | ||
write_file(&output_path, &output).unwrap(); | ||
|
||
if encrypt { | ||
eprintln!("encrypted {} as {}", input_path, output_path); | ||
} else { | ||
eprintln!("decrypted {} into {}", input_path, output_path); | ||
} | ||
} | ||
|
||
fn read_file(path: &str) -> Result<Vec<u8>, io::Error> { | ||
let mut file = File::open(path)?; | ||
let mut content = Vec::new(); | ||
file.read_to_end(&mut content)?; | ||
Ok(content) | ||
} | ||
|
||
fn write_file(path: &str, data: &[u8]) -> Result<(), io::Error> { | ||
let mut file = File::create(path)?; | ||
file.write_all(data)?; | ||
Ok(()) | ||
} |
Oops, something went wrong.