diff --git a/.gitignore b/.gitignore index 402113aaf..5d8fc1bad 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,7 @@ qrc_* Makefile *.qm /.qmake.stash + +# Rust +target/ +.cargo/ diff --git a/.travis.yml b/.travis.yml index 6bd884b0f..5843441bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,9 @@ branches: matrix: fast_finish: true + allow_failures: + - rust: beta + - rust: nightly include: - os: linux env: JOB=verify-commit-format @@ -24,6 +27,18 @@ matrix: # the actual compilin' - os: linux env: JOB=build-ubuntu-14-04 + - os: linux + env: JOB=build-rust + language: rust + rust: stable + - os: linux + env: JOB=build-rust + language: rust + rust: beta + - os: linux + env: JOB=build-rust + language: rust + rust: nightly - os: osx osx_image: xcode7.3 env: JOB=build-osx diff --git a/.travis/build-rust.sh b/.travis/build-rust.sh new file mode 100755 index 000000000..6ff00ff1d --- /dev/null +++ b/.travis/build-rust.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# +# Copyright © 2016 by The qTox Project Contributors +# +# This program is libre software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# used in travis to: +# - pull in dependencies for building libsodium +# - build required libsodium + +# Fail out on error +set -eu -o pipefail + +readonly LIBSODIUM_VER="1.0.11" + +build_libsodium() { + sudo apt-get update -qq + sudo apt-get install -y \ + build-essential \ + libtool \ + autotools-dev \ + automake \ + checkinstall \ + check \ + git \ + yasm \ + pkg-config || yes + + git clone https://github.com/jedisct1/libsodium.git libsodium \ + --branch $LIBSODIUM_VER \ + --depth 1 + + cd libsodium + ./autogen.sh + ./configure + make -j$(nproc) + sudo checkinstall \ + --install \ + --pkgname libsodium \ + --pkgversion $LIBSODIUM_VER \ + --nodoc \ + -y + sudo ldconfig + cd .. +} + +build_rust_bits() { + # TODO: make it a loop over paths once there are more rust bits + cd tools/update-server/qtox-updater-sign + cargo build --verbose + cargo test --verbose + # add `cargo doc` once it's needed? +} + +main() { + build_libsodium + build_rust_bits +} +main diff --git a/tools/update-server/qtox-updater-sign/Cargo.lock b/tools/update-server/qtox-updater-sign/Cargo.lock new file mode 100644 index 000000000..633b2f118 --- /dev/null +++ b/tools/update-server/qtox-updater-sign/Cargo.lock @@ -0,0 +1,41 @@ +[root] +name = "qtox-updater-sign" +version = "0.1.0" +dependencies = [ + "sodiumoxide 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libsodium-sys" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sodiumoxide" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libsodium-sys 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + diff --git a/tools/update-server/qtox-updater-sign/Cargo.toml b/tools/update-server/qtox-updater-sign/Cargo.toml new file mode 100644 index 000000000..3685eb3e0 --- /dev/null +++ b/tools/update-server/qtox-updater-sign/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "qtox-updater-sign" +version = "0.1.0" +authors = ["Zetok Zalbavar "] + +[dependencies] +sodiumoxide = "0.0.12" diff --git a/tools/update-server/qtox-updater-sign/README.md b/tools/update-server/qtox-updater-sign/README.md new file mode 100644 index 000000000..d3101114d --- /dev/null +++ b/tools/update-server/qtox-updater-sign/README.md @@ -0,0 +1,26 @@ +# qtox-updater-sign + +Simple program for signing releases. + +Requires a file named `qtox-updater-skey` in the working directory that +contains the secret key. + +To sign a release, either supply the name of the file to be signed as an +argument, or pipe data via stdin. + +```bash +./qtox-updater-sign sign-this-binary > signature_file +# or +./qtox-updater-sign < sign-this-binary > signature_file +``` + +# Compiling + +Requires `libsodium` and Rust. + +To build a debug version: `cargo build` + +To build a release version: `cargo build --release` + +This will produce `qtox-updater-sign` binary in `target/debug` or +`target/release` directory respectively. diff --git a/tools/update-server/qtox-updater-sign/main.cpp b/tools/update-server/qtox-updater-sign/main.cpp deleted file mode 100644 index 21f1c252d..000000000 --- a/tools/update-server/qtox-updater-sign/main.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include - -using namespace std; - -int main(int argc, char* argv[]) -{ - QFile io; - QByteArray msg; - if (argc > 1) - { - msg = QByteArray(argv[1]); - } - else - { - io.open(stdin, QIODevice::ReadOnly); - msg = io.readAll(); - io.close(); - } - io.open(stdout, QIODevice::WriteOnly); - - QFile skeyFile("qtox-updater-skey"); - if (!skeyFile.open(QIODevice::ReadOnly)) - { - io.write("ERROR: qtox-updater-sign can't open the secret (private) key file\n"); - io.close(); - return 1; - } - QByteArray skeyData = skeyFile.readAll(); - skeyFile.close(); - - unsigned char sig[crypto_sign_BYTES]; - crypto_sign_detached(sig, nullptr, (unsigned char*)msg.data(), msg.size(), (unsigned char*)skeyData.data()); - - io.write((char*)sig, crypto_sign_BYTES); - io.write(msg); - io.close(); - - return 0; -} - diff --git a/tools/update-server/qtox-updater-sign/qtox-updater-sign.pro b/tools/update-server/qtox-updater-sign/qtox-updater-sign.pro deleted file mode 100644 index 5f9c65af3..000000000 --- a/tools/update-server/qtox-updater-sign/qtox-updater-sign.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app -CONFIG += console c++11 -QT += core - -SOURCES += main.cpp - -LIBS += -lsodium diff --git a/tools/update-server/qtox-updater-sign/src/main.rs b/tools/update-server/qtox-updater-sign/src/main.rs new file mode 100644 index 000000000..4fb2a865a --- /dev/null +++ b/tools/update-server/qtox-updater-sign/src/main.rs @@ -0,0 +1,66 @@ +/* + Copyright © 2016 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +extern crate sodiumoxide; + +use std::io::prelude::*; +use std::io; +use std::fs::File; + +use sodiumoxide::crypto::sign::*; + +/// file that contains secret key +const SKEY_FNAME: &'static str = "qtox-updater-skey"; + +/// if there is more than just the program name in args, treat "1st" arg as the +/// data to sign +/// otherwise just read bytes from stdin +fn read_from_file_or_stdin(buf: &mut Vec) { + if std::env::args().count() > 1 { + let data = std::env::args().nth(1).expect("Failed to get fname"); + buf.extend_from_slice(&data.into_bytes()); + } else { + io::stdin().read_to_end(buf).expect("Failed to read stdin"); + } +} + +/// get SecretKey from `SKEY_FNAME` file +fn get_secret_key() -> SecretKey { + let mut skey_file = File::open(SKEY_FNAME) + .expect(&format!("ERROR: {} can't open the secret (private) key file\n", + std::env::args().next().unwrap())); + + let mut skey_bytes = Vec::with_capacity(SECRETKEYBYTES); + skey_file.read_to_end(&mut skey_bytes) + .expect(&format!("Failed to read {}", SKEY_FNAME)); + + SecretKey::from_slice(&skey_bytes[..SECRETKEYBYTES]) + .expect("Failed to get right amount of bytes for SecretKey") +} + + +fn main() { + let mut plaintext = Vec::new(); + read_from_file_or_stdin(&mut plaintext); + + let sk = get_secret_key(); + let signed = sign(&plaintext, &sk); + + io::stdout().write_all(&signed).expect("Failed to write signature"); +}