├── .gitignore ├── .rustfmt.toml ├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src ├── cli.rs ├── encryption.rs ├── error.rs ├── logic.rs ├── main.rs ├── secret.rs └── x25519.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | .idea -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 135 2 | use_field_init_shorthand = true 3 | use_try_shorthand = true 4 | use_small_heuristics = "Max" 5 | newline_style = "unix" 6 | edition = "2018" -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | - osx 4 | - windows 5 | language: rust 6 | cache: 7 | - cargo 8 | - directories: 9 | - $HOME/.rustup 10 | 11 | sudo: false 12 | rust: 13 | - stable 14 | - beta 15 | - nightly 16 | matrix: 17 | fast_finish: true 18 | allow_failures: 19 | - rust: nightly 20 | - rust: beta 21 | before_script: 22 | - if [ ${TRAVIS_RUST_VERSION} == "stable" ]; then 23 | rustup component add clippy-preview rustfmt; 24 | cargo fmt --all -- --check; 25 | cargo clippy -- -D clippy::all; 26 | if ! [[ -z "${TRAVIS_TAG}" ]]; then 27 | [[ ${TRAVIS_OS_NAME} == "windows" ]] && export EXTENSION=".exe"; 28 | export RELEASE="--release"; 29 | export BASE_NAME="lorenz"$EXTENSION 30 | export FILE_NAME=$TRAVIS_OS_NAME"_"$TRAVIS_TAG"_"; 31 | fi 32 | fi 33 | script: 34 | - cargo build --verbose $RELEASE 35 | - cargo test --verbose $RELEASE 36 | - ls target/*/ 37 | 38 | before_deploy: 39 | - mv target/release/$BASE_NAME $FILE_NAME$BASE_NAME 40 | - echo $BASE_NAME 41 | - echo $FILE_NAME 42 | - ls $FILE_NAME$BASE_NAME 43 | 44 | deploy: 45 | provider: releases 46 | api_key: 47 | secure: GX2XHpV7ji08v5rOvx0YdHd3AKc8JvzVFIc76SzZ5z9QOmpizHS2D4N/+jzw1eitCM+cl2V/Y/akklqNveOAXxibPN64vJHsfWkedVPntClF6dWZFSuOS8HP8B7AqvIHrDe9S19sgbS0VAti9KzpkGkzcuTy+lD9wwylVmWZTfQek25y7DyP/+N6sOBIt3Yyn9V0vLLZIzCeCLKFRrXhi+Lkosg7TJqNUAvsESVy5cLDUcslAf41gwY5z/W73NF179DnxgrqcpbHkdVoPM32A3FrRyDQ6jAXCmbNWBZunIx7rkwY85o0BE5AVCXDl8TLLEqiIKO8lUpqgjchi+wTnF2AM4cQWQikoyxzVc65RUkKrAkeH10dAN7F8AWl3bMud8CIZZBcr+J6vdH6ugOsWTIXfXhpxraIIe05YQbKSRCQ9sHJqNFUSrFISy54Z08HcY8qaz7kj3LeB77JMHDdFj6u9V43hCLr9eNgA23pLAejheqreOwEHyfx1ayxcWatXgR8xQxKqlYSHQ+0y1nKvm1LiIWFkjJ9Ax1/l0IC7sV31/cWXuXXE+Mkso7Apo9HYnJCprmPJ9FUqde8bd68uOFrvOZe15U2QnRBenCmonCAY7hwOzwCwY68DswiFjjq7O+7nDWobQDR+kF7Fe+QqjEp9zBQ7diLWItRFwSlK3w= 48 | file_glob: true 49 | file: $FILE_NAME$BASE_NAME 50 | skip_cleanup: true 51 | on: 52 | repo: elichai/Lorenz 53 | tags: true 54 | condition: $TRAVIS_RUST_VERSION = "stable" 55 | 56 | 57 | notifications: 58 | email: 59 | on_success: never 60 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ansi_term" 5 | version = "0.11.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "atty" 13 | version = "0.2.11" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 17 | "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 18 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 19 | ] 20 | 21 | [[package]] 22 | name = "autocfg" 23 | version = "0.1.4" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "bitflags" 28 | version = "1.1.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | 31 | [[package]] 32 | name = "byteorder" 33 | version = "1.3.1" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | 36 | [[package]] 37 | name = "cc" 38 | version = "1.0.37" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | 41 | [[package]] 42 | name = "cfg-if" 43 | version = "0.1.9" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | 46 | [[package]] 47 | name = "clap" 48 | version = "2.33.0" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | dependencies = [ 51 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 54 | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 57 | "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 58 | ] 59 | 60 | [[package]] 61 | name = "clear_on_drop" 62 | version = "0.2.3" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | dependencies = [ 65 | "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", 66 | ] 67 | 68 | [[package]] 69 | name = "cloudabi" 70 | version = "0.0.3" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | dependencies = [ 73 | "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 74 | ] 75 | 76 | [[package]] 77 | name = "curve25519-dalek" 78 | version = "1.1.4" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | dependencies = [ 81 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 82 | "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 83 | "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 84 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 85 | "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 86 | ] 87 | 88 | [[package]] 89 | name = "digest" 90 | version = "0.8.0" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | dependencies = [ 93 | "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 94 | ] 95 | 96 | [[package]] 97 | name = "fuchsia-cprng" 98 | version = "0.1.1" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | 101 | [[package]] 102 | name = "generic-array" 103 | version = "0.12.0" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | dependencies = [ 106 | "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 107 | ] 108 | 109 | [[package]] 110 | name = "heck" 111 | version = "0.3.1" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | dependencies = [ 114 | "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 115 | ] 116 | 117 | [[package]] 118 | name = "lazy_static" 119 | version = "1.3.0" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | 122 | [[package]] 123 | name = "libc" 124 | version = "0.2.58" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | 127 | [[package]] 128 | name = "lorenz" 129 | version = "0.1.0" 130 | dependencies = [ 131 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 132 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 133 | "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 134 | "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", 135 | "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 136 | "structopt 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", 137 | "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 138 | "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 139 | "zeroize 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", 140 | ] 141 | 142 | [[package]] 143 | name = "numtoa" 144 | version = "0.1.0" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | 147 | [[package]] 148 | name = "proc-macro2" 149 | version = "0.4.30" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | dependencies = [ 152 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 153 | ] 154 | 155 | [[package]] 156 | name = "quote" 157 | version = "0.6.12" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | dependencies = [ 160 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 161 | ] 162 | 163 | [[package]] 164 | name = "rand" 165 | version = "0.6.5" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | dependencies = [ 168 | "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 169 | "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 170 | "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 171 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 172 | "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 173 | "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 174 | "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 175 | "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 176 | "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 177 | "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 178 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 179 | ] 180 | 181 | [[package]] 182 | name = "rand_chacha" 183 | version = "0.1.1" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | dependencies = [ 186 | "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 187 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 188 | ] 189 | 190 | [[package]] 191 | name = "rand_core" 192 | version = "0.3.1" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | dependencies = [ 195 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 196 | ] 197 | 198 | [[package]] 199 | name = "rand_core" 200 | version = "0.4.0" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | 203 | [[package]] 204 | name = "rand_hc" 205 | version = "0.1.0" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | dependencies = [ 208 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 209 | ] 210 | 211 | [[package]] 212 | name = "rand_isaac" 213 | version = "0.1.1" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | dependencies = [ 216 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 217 | ] 218 | 219 | [[package]] 220 | name = "rand_jitter" 221 | version = "0.1.4" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | dependencies = [ 224 | "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 225 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 226 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 227 | ] 228 | 229 | [[package]] 230 | name = "rand_os" 231 | version = "0.1.3" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | dependencies = [ 234 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 235 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 236 | "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 237 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 238 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 239 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 240 | ] 241 | 242 | [[package]] 243 | name = "rand_pcg" 244 | version = "0.1.2" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | dependencies = [ 247 | "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 248 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 249 | ] 250 | 251 | [[package]] 252 | name = "rand_xorshift" 253 | version = "0.1.1" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | dependencies = [ 256 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 257 | ] 258 | 259 | [[package]] 260 | name = "rdrand" 261 | version = "0.4.0" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | dependencies = [ 264 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 265 | ] 266 | 267 | [[package]] 268 | name = "redox_syscall" 269 | version = "0.1.54" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | 272 | [[package]] 273 | name = "redox_termios" 274 | version = "0.1.1" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | dependencies = [ 277 | "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", 278 | ] 279 | 280 | [[package]] 281 | name = "remove_dir_all" 282 | version = "0.5.1" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | dependencies = [ 285 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 286 | ] 287 | 288 | [[package]] 289 | name = "ring" 290 | version = "0.14.6" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | dependencies = [ 293 | "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", 294 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 295 | "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 296 | "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 297 | "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 298 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 299 | ] 300 | 301 | [[package]] 302 | name = "rustc-hex" 303 | version = "2.0.1" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | 306 | [[package]] 307 | name = "spin" 308 | version = "0.5.0" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | 311 | [[package]] 312 | name = "strsim" 313 | version = "0.8.0" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | 316 | [[package]] 317 | name = "structopt" 318 | version = "0.2.17" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | dependencies = [ 321 | "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", 322 | "structopt-derive 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", 323 | ] 324 | 325 | [[package]] 326 | name = "structopt-derive" 327 | version = "0.2.17" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | dependencies = [ 330 | "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 331 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 332 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 333 | "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", 334 | ] 335 | 336 | [[package]] 337 | name = "subtle" 338 | version = "2.1.0" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | 341 | [[package]] 342 | name = "syn" 343 | version = "0.15.34" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | dependencies = [ 346 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 347 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 348 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 349 | ] 350 | 351 | [[package]] 352 | name = "synstructure" 353 | version = "0.10.2" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | dependencies = [ 356 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 357 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 358 | "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", 359 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 360 | ] 361 | 362 | [[package]] 363 | name = "tempfile" 364 | version = "3.0.8" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | dependencies = [ 367 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 368 | "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 369 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 370 | "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", 371 | "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 372 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 373 | ] 374 | 375 | [[package]] 376 | name = "termion" 377 | version = "1.5.2" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | dependencies = [ 380 | "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 381 | "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 382 | "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", 383 | "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 384 | ] 385 | 386 | [[package]] 387 | name = "textwrap" 388 | version = "0.11.0" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | dependencies = [ 391 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 392 | ] 393 | 394 | [[package]] 395 | name = "typenum" 396 | version = "1.10.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | 399 | [[package]] 400 | name = "unicode-segmentation" 401 | version = "1.3.0" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | 404 | [[package]] 405 | name = "unicode-width" 406 | version = "0.1.5" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | 409 | [[package]] 410 | name = "unicode-xid" 411 | version = "0.1.0" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | 414 | [[package]] 415 | name = "untrusted" 416 | version = "0.6.2" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | 419 | [[package]] 420 | name = "vec_map" 421 | version = "0.8.1" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | 424 | [[package]] 425 | name = "winapi" 426 | version = "0.3.7" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | dependencies = [ 429 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 430 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 431 | ] 432 | 433 | [[package]] 434 | name = "winapi-i686-pc-windows-gnu" 435 | version = "0.4.0" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | 438 | [[package]] 439 | name = "winapi-x86_64-pc-windows-gnu" 440 | version = "0.4.0" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | 443 | [[package]] 444 | name = "x25519-dalek" 445 | version = "0.5.2" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | dependencies = [ 448 | "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 449 | "curve25519-dalek 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 450 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 451 | ] 452 | 453 | [[package]] 454 | name = "zeroize" 455 | version = "0.9.1" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | dependencies = [ 458 | "zeroize_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 459 | ] 460 | 461 | [[package]] 462 | name = "zeroize_derive" 463 | version = "0.9.0" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | dependencies = [ 466 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 467 | "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 468 | "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", 469 | "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", 470 | ] 471 | 472 | [metadata] 473 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 474 | "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" 475 | "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" 476 | "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" 477 | "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" 478 | "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" 479 | "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" 480 | "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" 481 | "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" 482 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 483 | "checksum curve25519-dalek 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "750226d75fc2f5a8daec6e7477624e258674023eb73d8d647f63b943ca182a4a" 484 | "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" 485 | "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 486 | "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" 487 | "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 488 | "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" 489 | "checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" 490 | "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" 491 | "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" 492 | "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" 493 | "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 494 | "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 495 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 496 | "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" 497 | "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 498 | "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 499 | "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" 500 | "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" 501 | "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" 502 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 503 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 504 | "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" 505 | "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 506 | "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" 507 | "checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" 508 | "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" 509 | "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" 510 | "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 511 | "checksum structopt 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c767a8971f53d7324583085deee2e230903be09e52fb27df9af94c5cb2b43c31" 512 | "checksum structopt-derive 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c57a30c87454ced2186f62f940e981746e8cbbe026d52090c8c4352b636f8235" 513 | "checksum subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01dca13cf6c3b179864ab3292bd794e757618d35a7766b7c46050c614ba00829" 514 | "checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" 515 | "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" 516 | "checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" 517 | "checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" 518 | "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 519 | "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" 520 | "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" 521 | "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" 522 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 523 | "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" 524 | "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 525 | "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" 526 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 527 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 528 | "checksum x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee1585dc1484373cbc1cee7aafda26634665cf449436fd6e24bfd1fad230538" 529 | "checksum zeroize 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2ea4afc22e9497e26b42bf047083c30f7e3ca566f3bcd7187f83d18b327043" 530 | "checksum zeroize_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afd1469e4bbca3b96606d26ba6e9bd6d3aed3b1299c82b92ec94377d22d78dbc" 531 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lorenz" 3 | version = "0.1.1" 4 | license = "MIT/Apache-2.0" 5 | authors = ["Elichai "] 6 | repository = "https://github.com/elichai/lorenz" 7 | readme = "README.md" 8 | edition = "2018" 9 | description = "File encryption for multiple participants" 10 | categories = ["cryptography", "command-line-utilities"] 11 | keywords = ["crypto", "cli"] 12 | 13 | [dependencies] 14 | ring = "0.14.6" 15 | x25519-dalek = "0.5.2" 16 | rand_os = "0.1.3" 17 | lazy_static = "1.3.0" 18 | structopt = "0.2" 19 | rustc-hex = "2.0" 20 | zeroize = "0.9.1" 21 | 22 | [dev-dependencies] 23 | tempfile = "3.0" 24 | rand = "0.6.5" 25 | 26 | 27 | [badges] 28 | travis-ci = { repository = "elichai/lorenz" } 29 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Elichai Turkel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lorenz 2 | [![Build Status](https://travis-ci.org/elichai/lorenz.svg?branch=master)](https://travis-ci.org/elichai/lorenz) 3 | [![Latest version](https://img.shields.io/crates/v/lorenz.svg)](https://crates.io/crates/lorenz) 4 | ![License](https://img.shields.io/crates/l/lorenz.svg) 5 | [![dependency status](https://deps.rs/repo/github/elichai/lorenz/status.svg)](https://deps.rs/repo/github/elichai/lorenz) 6 | 7 | A Rust binary for file encryption to multiple participants. 8 | 9 | 10 | ## Installation 11 | 12 | ### Archlinux 13 | TBD 14 | 15 | ### On Ubuntu_... and other Debian-based Linux distributions_ 16 | TBD 17 | 18 | ### On Gentoo 19 | TBD 20 | ### From Snap 21 | TBD 22 | 23 | ### On macOS 24 | TBD 25 | 26 | ### On Windows 27 | TBD 28 | 29 | ### From Sources 30 | With Rust's package manager cargo, you can install Lorenz via: 31 | 32 | ```sh 33 | cargo install --force lorenz 34 | ``` 35 | 36 | ### From Binaries 37 | 38 | The [release page](https://github.com/elichai/lorenz/releases) includes precompiled binaries for Linux, macOS and Windows. 39 | 40 | 41 | 42 | 43 | # Usage 44 | 45 | Generating keys: 46 | `lorenz generate-keys ` 47 | 48 | Encrypt a file: 49 | `lorenz encrypt ` 50 | 51 | Either of the associated private keys will be able to decrypt the file. 52 | Decrypt: 53 | `lorenz decrypt ` 54 | 55 | # Example 56 | ```sh 57 | $ lorenz generate-keys 3 58 | key 1: 59 | privateKey: 0x40a8196f56f902d965fdf4eaadce44b651206bec8eed868d3c8b65df2f9df540 60 | publicKey: 0x6fa09e7d6874dcb2410390636477d87cdc8a5bbf2f9d858337f8ff73e509d340 61 | 62 | key 2: 63 | privateKey: 0x5814cdd862fd5704d3235dca766019372c3bf8d213a87ed867506af146dccd7e 64 | publicKey: 0x6a27b32d6144888657b40328d3d6472127ea9835d7fd7a2c8327b0d72174737c 65 | 66 | key 3: 67 | privateKey: 0x10d83487bdf1387fea1511005bb39a90d33a43f3d4bdcaa41261714abb5bcb52 68 | publicKey: 0xc9f24018fc12249b65e5d0d1058c91f17b14979373621e25600ac1ae32b45738 69 | 70 | $ lorenz encrypt 0x6fa09e7d6874dcb2410390636477d87cdc8a5bbf2f9d858337f8ff73e509d340 0x6a27b32d6144888657b40328d3d6472127ea9835d7fd7a2c8327b0d72174737c 0xc9f24018fc12249b65e5d0d1058c91f17b14979373621e25600ac1ae32b45738 test.txt 71 | 72 | $ lorenz decrypt 0x10d83487bdf1387fea1511005bb39a90d33a43f3d4bdcaa41261714abb5bcb52 test.txt.lorenz 73 | 74 | ``` 75 | -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | use crate::x25519::UserSecretKey; 2 | use rustc_hex::{FromHex, FromHexError}; 3 | use std::path::PathBuf; 4 | use structopt::StructOpt; 5 | 6 | #[derive(Debug, StructOpt)] 7 | #[structopt(name = "Lorenz", about = "A tool for encrypting/decrypting a file for multiple participants.")] 8 | pub enum Options { 9 | /// Generate Pairs of keys. 10 | #[structopt(name = "generate-keys")] 11 | GenerateKeys { 12 | #[structopt(default_value = "1")] 13 | amount: u8, 14 | }, 15 | /// Encrypt a file 16 | #[structopt(name = "encrypt")] 17 | Encrypt { 18 | #[structopt(parse(try_from_str = "parse_hex32"), raw(required = "true"))] 19 | public_keys: Vec<[u8; 32]>, 20 | #[structopt(parse(from_os_str))] 21 | file: PathBuf, 22 | #[structopt(long, default_value = "AES")] 23 | mode: String, 24 | }, 25 | /// Decrypt a file 26 | #[structopt(name = "decrypt")] 27 | Decrypt { 28 | #[structopt(parse(try_from_str))] 29 | private_key: UserSecretKey, 30 | #[structopt(parse(from_os_str))] 31 | file: PathBuf, 32 | #[structopt(long, default_value = "AES")] 33 | mode: String, 34 | }, 35 | } 36 | 37 | pub fn parse_hex32(hex: &str) -> Result<[u8; 32], FromHexError> { 38 | let hex = if "0x" == hex.chars().take(2).collect::().as_str() { hex.chars().skip(2).collect() } else { hex.to_owned() }; 39 | if hex.len() != 64 { 40 | // TODO: formalize an error 41 | return Err(FromHexError::InvalidHexLength); 42 | } 43 | let hex_vec: Vec = hex.from_hex()?; 44 | let mut result = [0u8; 32]; 45 | result.copy_from_slice(&hex_vec); 46 | Ok(result) 47 | } 48 | -------------------------------------------------------------------------------- /src/encryption.rs: -------------------------------------------------------------------------------- 1 | use crate::Error; 2 | use ring::aead::{self, open_in_place, seal_in_place, Aad, Nonce, OpeningKey, SealingKey, AES_256_GCM, CHACHA20_POLY1305, NONCE_LEN}; 3 | use ring::rand::{SecureRandom, SystemRandom}; 4 | use std::str::FromStr; 5 | use structopt::clap::{Error as ClapError, ErrorKind as ClapErrorKind}; 6 | use zeroize::Zeroizing; 7 | 8 | #[derive(Copy, Clone)] 9 | pub enum Scheme { 10 | AES256GCM, 11 | Chacha20Poly1305, 12 | } 13 | 14 | pub fn encrypt_data(key: &[u8], mut data: Vec, scheme: Scheme) -> Result, Error> { 15 | let algorithm = scheme.get_algorithm(); 16 | if key.len() != algorithm.key_len() { 17 | return Err(Error::BadKeyLength); 18 | } 19 | let key = SealingKey::new(algorithm, key)?; 20 | let (nonce, raw_nonce) = get_random_nonce()?; 21 | 22 | data.extend(vec![0u8; algorithm.tag_len()]); 23 | let s = seal_in_place(&key, nonce, Aad::empty(), &mut data, algorithm.tag_len())?; 24 | 25 | debug_assert_eq!(s, data.len()); 26 | 27 | data.extend(&raw_nonce); 28 | 29 | Ok(data) 30 | } 31 | 32 | pub fn decrypt_data(key: &[u8], mut data: Vec, scheme: Scheme) -> Result, Error> { 33 | let algorithm = scheme.get_algorithm(); 34 | if key.len() != algorithm.key_len() { 35 | return Err(Error::BadKeyLength); 36 | } 37 | let nonce = data.split_off(data.len() - NONCE_LEN); 38 | let nonce = Nonce::try_assume_unique_for_key(&nonce).unwrap(); // Can never fail. 39 | 40 | let key = OpeningKey::new(algorithm, key)?; 41 | let mut result = Zeroizing::new(data); 42 | 43 | let plaintext = open_in_place(&key, nonce, Aad::empty(), 0, &mut result)?; 44 | 45 | Ok(plaintext.to_vec()) 46 | } 47 | 48 | fn get_random_nonce() -> Result<(Nonce, [u8; 12]), Error> { 49 | let rand_gen = SystemRandom::new(); 50 | let mut nonce = [0u8; NONCE_LEN]; 51 | rand_gen.fill(&mut nonce)?; 52 | Ok((Nonce::assume_unique_for_key(nonce), nonce)) 53 | } 54 | 55 | impl Scheme { 56 | pub fn get_algorithm(self) -> &'static aead::Algorithm { 57 | match self { 58 | Scheme::AES256GCM => &AES_256_GCM, 59 | Scheme::Chacha20Poly1305 => &CHACHA20_POLY1305, 60 | } 61 | } 62 | 63 | pub fn get_encrypted_key_size(self) -> usize { 64 | let algorithm = self.get_algorithm(); 65 | algorithm.key_len() + algorithm.tag_len() + algorithm.nonce_len() 66 | } 67 | } 68 | 69 | impl FromStr for Scheme { 70 | type Err = ClapError; 71 | 72 | fn from_str(mode: &str) -> Result { 73 | match mode.to_lowercase().as_str() { 74 | "aes" | "aes256" => Ok(Scheme::AES256GCM), 75 | "chacha" | "chacha20" | "chacha20poly1305" => Ok(Scheme::Chacha20Poly1305), 76 | a => Err(ClapError::with_description( 77 | &format!("{} Mode isn't supported, please choose one of these: AES/Chacha20", a), 78 | ClapErrorKind::InvalidValue, 79 | )), 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use rand_os::rand_core::Error as RandError; 2 | use ring::error::Unspecified as RingError; 3 | use std::error::Error as StdError; 4 | use std::fmt; 5 | use std::io; 6 | use structopt::clap::{Error as ClapError, ErrorKind as ClapErrorKind}; 7 | 8 | #[derive(Debug)] 9 | pub enum Error { 10 | IoError(io::Error), 11 | RngError(RandError), 12 | RingError, 13 | BadKeyLength, 14 | BadKey, 15 | } 16 | 17 | impl Error { 18 | pub fn key_length(_: E) -> Self { 19 | Error::BadKeyLength 20 | } 21 | pub fn bad_key(_: E) -> Self { 22 | Error::BadKey 23 | } 24 | } 25 | 26 | impl StdError for Error {} 27 | 28 | impl fmt::Display for Error { 29 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 30 | use Error::*; 31 | match self { 32 | IoError(e) => writeln!(f, "Lorenz Error IO: {}", e), 33 | RngError(e) => writeln!(f, "Lorenz Error RNG: {}", e), 34 | RingError => writeln!(f, "Lorenz Error: Failed Encrypting/Decrypting data"), 35 | BadKeyLength => writeln!(f, "Lorenz Error: Key isn't the right length"), 36 | BadKey => writeln!(f, "Lorenz Error: Couldn't find the right key"), 37 | } 38 | } 39 | } 40 | 41 | impl From for Error { 42 | fn from(err: io::Error) -> Self { 43 | Error::IoError(err) 44 | } 45 | } 46 | 47 | impl From for Error { 48 | fn from(err: RandError) -> Self { 49 | Error::RngError(err) 50 | } 51 | } 52 | 53 | impl From for Error { 54 | fn from(_: RingError) -> Self { 55 | Error::RingError 56 | } 57 | } 58 | 59 | impl From for ClapError { 60 | fn from(err: Error) -> ClapError { 61 | use Error::*; 62 | match err { 63 | IoError(e) => e.into(), 64 | RngError(e) => ClapError::with_description(e.description(), ClapErrorKind::Io), 65 | _ => unimplemented!(), 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/logic.rs: -------------------------------------------------------------------------------- 1 | use crate::x25519::*; 2 | use crate::*; 3 | use encryption::Scheme; 4 | use std::fs::*; 5 | use std::io::{self, Read, Seek, SeekFrom, Write}; 6 | use x25519_dalek::PublicKey; 7 | 8 | fn file_len(file: &File) -> usize { 9 | file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0) 10 | } 11 | 12 | pub fn encrypt_file_with_keys(input_file: &mut File, keys: Vec, output: &mut File, scheme: Scheme) -> Result<(), Error> { 13 | let mut input = Vec::with_capacity(file_len(&input_file)); 14 | input_file.read_to_end(&mut input)?; 15 | let aes = Secret::generate32()?; 16 | let ephemeral = x25519::EphemeralKey::new()?; 17 | output.write_all(ephemeral.get_public().as_bytes())?; 18 | output.write_all(&[keys.len() as u8])?; 19 | 20 | for key in &keys { 21 | let shared = ephemeral.derive_secret(&key, 32); 22 | let enc_key = encryption::encrypt_data(shared.as_ref(), aes.clone().into_vec(), scheme)?; 23 | output.write_all(&enc_key)?; 24 | } 25 | 26 | let enc_file = encryption::encrypt_data(aes.as_ref(), input, scheme)?; 27 | output.write_all(&enc_file)?; 28 | Ok(()) 29 | } 30 | 31 | pub fn decrypt_file_with_keys(input_file: &mut File, key: UserSecretKey, output: &mut File, scheme: Scheme) -> Result<(), Error> { 32 | let mut pubkey = [0u8; 32]; 33 | input_file.read_exact(&mut pubkey)?; 34 | let amount = take(input_file)?; 35 | 36 | let shared = key.derive_secret(&pubkey.into(), 32); 37 | let (key, left) = find_encrypted_key(input_file, shared, amount, scheme); 38 | let key = key.ok_or(Error::BadKey)?; 39 | input_file.seek(SeekFrom::Current(i64::from(left) * scheme.get_encrypted_key_size() as i64))?; 40 | 41 | let data_size = file_len(input_file) - 32 - 1 - amount as usize * scheme.get_encrypted_key_size(); 42 | let mut data = Vec::with_capacity(data_size); 43 | 44 | input_file.read_to_end(&mut data)?; 45 | 46 | let original = encryption::decrypt_data(key.as_ref(), data, scheme)?; 47 | output.write_all(&original)?; 48 | 49 | Ok(()) 50 | } 51 | 52 | fn take(reader: &mut R) -> io::Result { 53 | let mut b = [0]; 54 | reader.read_exact(&mut b)?; 55 | Ok(b[0]) 56 | } 57 | 58 | fn find_encrypted_key(f: &mut R, shared: Secret, amount: u8, scheme: Scheme) -> (Option, u8) { 59 | let key_size = scheme.get_encrypted_key_size(); 60 | for i in 1..=amount { 61 | let mut encrypted_key = vec![0u8; key_size]; 62 | match f.read_exact(&mut encrypted_key).ok() { 63 | None => return (None, amount - i), 64 | Some(()) => (), 65 | }; 66 | match encryption::decrypt_data(shared.as_ref(), encrypted_key, scheme) { 67 | Err(_) => continue, 68 | Ok(key) => return (Some(Secret::from_vec(key)), amount - i), 69 | } 70 | } 71 | (None, 0) 72 | } 73 | 74 | #[cfg(test)] 75 | mod tests { 76 | use super::*; 77 | use crate::tests::{generate_random_keys, get_rand_file}; 78 | use rand::{seq::SliceRandom, thread_rng, Rng}; 79 | use tempfile::tempfile; 80 | 81 | #[test] 82 | fn encryption_decryption_test() { 83 | for _ in 0..15 { 84 | internal_test(Scheme::AES256GCM); 85 | internal_test(Scheme::Chacha20Poly1305); 86 | } 87 | } 88 | 89 | fn internal_test(scheme: Scheme) { 90 | let mut rng = thread_rng(); 91 | let mut original = get_rand_file(); 92 | let mut encrypted = tempfile().unwrap(); 93 | let mut decrypted = tempfile().unwrap(); 94 | let keys = generate_random_keys(rng.gen()); 95 | let decrypt_with = keys.choose(&mut rng).unwrap().0.clone(); 96 | let pub_keys = keys.iter().map(|(_, p)| p).cloned().collect(); 97 | 98 | encrypt_file_with_keys(&mut original, pub_keys, &mut encrypted, scheme).unwrap(); 99 | encrypted.seek(SeekFrom::Start(0)).unwrap(); 100 | decrypt_file_with_keys(&mut encrypted, decrypt_with, &mut decrypted, scheme).unwrap(); 101 | 102 | original.seek(SeekFrom::Start(0)).unwrap(); 103 | decrypted.seek(SeekFrom::Start(0)).unwrap(); 104 | 105 | let (mut before, mut after) = (Vec::with_capacity(1986), Vec::with_capacity(1986)); 106 | original.read_to_end(&mut before).unwrap(); 107 | decrypted.read_to_end(&mut after).unwrap(); 108 | assert_eq!(before, after); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | mod cli; 4 | mod encryption; 5 | mod error; 6 | mod logic; 7 | mod secret; 8 | mod x25519; 9 | 10 | use crate::encryption::Scheme; 11 | use crate::x25519::UserSecretKey; 12 | use cli::Options; 13 | pub use error::Error; 14 | pub use secret::Secret; 15 | use std::fs::File; 16 | use std::path::{Path, PathBuf}; 17 | use std::str::FromStr; 18 | use structopt::clap::{Error as ClapError, ErrorKind as ClapErrorKind}; 19 | use structopt::StructOpt; 20 | use x25519_dalek::PublicKey; 21 | 22 | fn main() { 23 | let opt = Options::from_args(); 24 | if let Err(e) = handle_cli(opt) { 25 | e.exit(); 26 | } 27 | } 28 | 29 | fn handle_cli(opt: Options) -> Result<(), ClapError> { 30 | match opt { 31 | Options::GenerateKeys { amount } => { 32 | for i in 1..=amount { 33 | let key = UserSecretKey::new()?; 34 | println!("key {}: \n{}", i, key); 35 | } 36 | } 37 | Options::Encrypt { public_keys, file, mode } => { 38 | let mut input = File::open(&file)?; 39 | let mut output = File::create(add_lorenz_extenstion(&file))?; 40 | let scheme = Scheme::from_str(&mode)?; 41 | let public_keys = public_keys.into_iter().map(PublicKey::from).collect(); 42 | logic::encrypt_file_with_keys(&mut input, public_keys, &mut output, scheme)?; 43 | } 44 | Options::Decrypt { private_key, file, mode } => { 45 | let mut input = File::open(&file)?; 46 | let output_path = remove_lorenz_extenstion(file)?; 47 | let mut output = File::create(&output_path)?; 48 | let scheme = Scheme::from_str(&mode)?; 49 | logic::decrypt_file_with_keys(&mut input, private_key, &mut output, scheme)?; 50 | } 51 | }; 52 | 53 | Ok(()) 54 | } 55 | 56 | fn add_lorenz_extenstion>(path: P) -> PathBuf { 57 | let mut path = path.as_ref().as_os_str().to_owned(); 58 | path.push(".lorenz"); 59 | path.into() 60 | } 61 | 62 | fn remove_lorenz_extenstion>(path: P) -> Result { 63 | let err = ClapError::with_description("Bad File, doesn't end with `lorenz` extension", ClapErrorKind::InvalidValue); 64 | let path = path.as_ref(); 65 | if let Some(ext) = path.extension() { 66 | if ext == "lorenz" { 67 | let mut res = path.to_owned(); 68 | let file_without_path = path.file_stem().ok_or(err)?; 69 | res.set_file_name(file_without_path); 70 | return Ok(res); 71 | } 72 | } 73 | Err(err) 74 | } 75 | 76 | #[cfg(test)] 77 | mod tests { 78 | use rand::{thread_rng, RngCore}; 79 | use std::fs::File; 80 | use std::io::{self, Read, Seek, SeekFrom, Write}; 81 | 82 | use super::*; 83 | use crate::encryption::Scheme; 84 | use crate::x25519::UserSecretKey; 85 | use tempfile::tempfile; 86 | 87 | #[test] 88 | fn full_test() { 89 | let mut input = get_rand_file(); 90 | let mut encrypted = tempfile().unwrap(); 91 | let mut decrypted = tempfile().unwrap(); 92 | 93 | let mut keys = encrypt(6, &mut input, &mut encrypted); 94 | 95 | decrypt(keys.remove(4), &mut encrypted, &mut decrypted); 96 | 97 | let mut before = Vec::new(); 98 | let mut after = Vec::new(); 99 | 100 | input.read_to_end(&mut before).unwrap(); 101 | decrypted.read_to_end(&mut after).unwrap(); 102 | assert_eq!(before, after); 103 | } 104 | 105 | pub fn get_rand_file() -> File { 106 | let mut input = vec![0u8; 1986]; 107 | let mut rng = thread_rng(); 108 | rng.fill_bytes(&mut input); 109 | let mut f = tempfile().unwrap(); 110 | f.write_all(&input).unwrap(); 111 | f.seek(SeekFrom::Start(0)).unwrap(); 112 | f 113 | } 114 | 115 | fn take(reader: &mut R) -> io::Result { 116 | let mut b = [0]; 117 | reader.read_exact(&mut b)?; 118 | Ok(b[0]) 119 | } 120 | 121 | fn decrypt(key: UserSecretKey, mut encrypted: &mut File, output: &mut File) { 122 | let mut pubkey = [0u8; 32]; 123 | encrypted.read_exact(&mut pubkey).unwrap(); 124 | let amount = take(&mut encrypted).unwrap(); 125 | 126 | let shared = key.derive_secret(&pubkey.into(), 32); 127 | let (aes_key, left) = find_aes_key(&mut encrypted, shared, amount); 128 | let aes_key = aes_key.unwrap(); 129 | encrypted.seek(SeekFrom::Current(left as i64 * 60)).unwrap(); 130 | 131 | let file_size = encrypted.metadata().unwrap().len() as usize - 32 - 1 - (60 * amount as usize); 132 | 133 | let mut file_data = Vec::with_capacity(file_size); 134 | encrypted.read_to_end(&mut file_data).unwrap(); 135 | 136 | let original = encryption::decrypt_data(aes_key.as_ref(), file_data, Scheme::AES256GCM).unwrap(); 137 | output.write_all(&original).unwrap(); 138 | 139 | encrypted.seek(SeekFrom::Start(0)).unwrap(); 140 | output.seek(SeekFrom::Start(0)).unwrap(); 141 | } 142 | 143 | fn find_aes_key(f: &mut R, shared: Secret, amount: u8) -> (Option, u8) { 144 | for i in 1..=amount { 145 | let mut encrypted_key = vec![0u8; 60]; 146 | match f.read_exact(&mut encrypted_key).ok() { 147 | None => return (None, amount - i), 148 | Some(()) => (), 149 | }; 150 | match encryption::decrypt_data(shared.as_ref(), encrypted_key, Scheme::AES256GCM) { 151 | Err(_) => continue, 152 | Ok(key) => return (Some(Secret::from_vec(key)), amount - i), 153 | } 154 | } 155 | (None, 0) 156 | } 157 | 158 | fn encrypt(keys: u8, input_file: &mut File, output: &mut File) -> Vec { 159 | let mut input = Vec::with_capacity(1987); 160 | input_file.read_to_end(&mut input).unwrap(); 161 | let aes = Secret::generate32().unwrap(); 162 | let ephemeral = x25519::EphemeralKey::new().unwrap(); 163 | 164 | output.write_all(ephemeral.get_public().as_bytes()).unwrap(); 165 | 166 | output.write_all(&[keys]).unwrap(); 167 | 168 | let keys = generate_random_keys(keys); 169 | for (_, public) in &keys { 170 | let shared = ephemeral.derive_secret(public, 32); 171 | let enc_key = encryption::encrypt_data(shared.as_ref(), aes.clone().into_vec(), Scheme::AES256GCM).unwrap(); 172 | output.write_all(&enc_key).unwrap(); 173 | } 174 | 175 | let enc_file = encryption::encrypt_data(aes.as_ref(), input, Scheme::AES256GCM).unwrap(); 176 | output.write_all(&enc_file).unwrap(); 177 | output.seek(SeekFrom::Start(0)).unwrap(); 178 | input_file.seek(SeekFrom::Start(0)).unwrap(); 179 | 180 | keys.into_iter().map(|(key, _)| key).collect() 181 | } 182 | 183 | pub fn generate_random_keys(amount: u8) -> Vec<(UserSecretKey, PublicKey)> { 184 | let mut res = Vec::with_capacity(amount as usize); 185 | for _ in 0..amount { 186 | let key = UserSecretKey::new().unwrap(); 187 | let public = key.get_public(); 188 | res.push((key, public)); 189 | } 190 | res 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/secret.rs: -------------------------------------------------------------------------------- 1 | use crate::Error; 2 | use rand_os::rand_core::RngCore; 3 | use rand_os::OsRng; 4 | use std::boxed::Box; 5 | use std::pin::Pin; 6 | use zeroize::Zeroize; 7 | 8 | #[derive(Clone, Zeroize)] 9 | #[zeroize(drop)] 10 | pub struct Secret(Pin>); 11 | 12 | impl Secret { 13 | pub fn from_vec(vec: Vec) -> Self { 14 | Self(vec.into_boxed_slice().into()) 15 | } 16 | 17 | pub fn generate32() -> Result { 18 | let mut rng = OsRng::new()?; 19 | let mut vec = vec![0u8; 32]; 20 | rng.fill_bytes(&mut vec); 21 | Ok(Self::from_vec(vec)) 22 | } 23 | 24 | pub fn into_vec(self) -> Vec { 25 | (*self.0).into() 26 | } 27 | } 28 | 29 | impl AsRef<[u8]> for Secret { 30 | #[inline] 31 | fn as_ref(&self) -> &[u8] { 32 | &self.0 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/x25519.rs: -------------------------------------------------------------------------------- 1 | use crate::secret::Secret; 2 | use crate::Error; 3 | use lazy_static::lazy_static; 4 | use rand_os::OsRng; 5 | use ring::digest::SHA256; 6 | use ring::hkdf; 7 | use ring::hmac::SigningKey; 8 | use rustc_hex::{FromHex, ToHex}; 9 | use std::fmt; 10 | use std::str::FromStr; 11 | use x25519_dalek::{PublicKey, StaticSecret}; 12 | use zeroize::{Zeroize, Zeroizing}; 13 | 14 | lazy_static! { 15 | static ref SALT: SigningKey = SigningKey::new(&SHA256, b"Lorenz"); 16 | } 17 | 18 | pub struct EphemeralKey(StaticSecret); 19 | 20 | impl EphemeralKey { 21 | pub fn new() -> Result { 22 | let mut rng = OsRng::new()?; 23 | Ok(Self(StaticSecret::new(&mut rng))) 24 | } 25 | 26 | pub fn derive_secret(&self, other: &PublicKey, len: usize) -> Secret { 27 | let mut res = vec![0u8; len]; 28 | let shared = self.0.diffie_hellman(&other); 29 | hkdf::extract_and_expand(&SALT, shared.as_bytes(), &[], &mut res); 30 | 31 | Secret::from_vec(res) 32 | } 33 | 34 | pub fn get_public(&self) -> PublicKey { 35 | PublicKey::from(&self.0) 36 | } 37 | } 38 | 39 | impl From<[u8; 32]> for EphemeralKey { 40 | #[inline] 41 | fn from(bytes: [u8; 32]) -> EphemeralKey { 42 | EphemeralKey(bytes.into()) 43 | } 44 | } 45 | 46 | #[cfg_attr(test, derive(Clone))] 47 | pub struct UserSecretKey(StaticSecret); 48 | 49 | impl UserSecretKey { 50 | pub fn new() -> Result { 51 | let mut rng = OsRng::new()?; 52 | Ok(Self(StaticSecret::new(&mut rng))) 53 | } 54 | 55 | pub fn derive_secret(&self, other: &PublicKey, len: usize) -> Secret { 56 | let mut res = vec![0u8; len]; 57 | let shared = self.0.diffie_hellman(&other); 58 | hkdf::extract_and_expand(&SALT, shared.as_bytes(), &[], &mut res); 59 | 60 | Secret::from_vec(res) 61 | } 62 | 63 | pub fn get_public(&self) -> PublicKey { 64 | PublicKey::from(&self.0) 65 | } 66 | } 67 | 68 | impl fmt::Display for UserSecretKey { 69 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 70 | let mut private = self.0.to_bytes().to_hex::(); 71 | let public = self.get_public().as_bytes().to_hex::(); 72 | writeln!(f, "privateKey: 0x{}", private)?; 73 | private.zeroize(); 74 | writeln!(f, "publicKey: 0x{}", public) 75 | } 76 | } 77 | 78 | pub fn secret_parse_hex32(hex: &str) -> Result, Error> { 79 | let mut first_chars = hex.chars().take(2).collect::(); 80 | let mut hex = if first_chars.as_str() == "0x" { hex.chars().skip(2).collect() } else { hex.to_owned() }; 81 | first_chars.zeroize(); 82 | drop(first_chars); 83 | if hex.len() != 64 { 84 | // TODO: formalize an error 85 | hex.zeroize(); 86 | return Err(Error::BadKeyLength); 87 | } 88 | let mut hex_vec: Vec = hex.from_hex().map_err(Error::bad_key)?; 89 | let mut result = Zeroizing::new([0u8; 32]); 90 | result.copy_from_slice(&hex_vec); 91 | hex_vec.zeroize(); 92 | drop(hex_vec); 93 | Ok(result) 94 | } 95 | 96 | impl fmt::Debug for UserSecretKey { 97 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 98 | write!(f, "{}", self) 99 | } 100 | } 101 | 102 | impl FromStr for UserSecretKey { 103 | type Err = Error; 104 | 105 | fn from_str(hex: &str) -> Result { 106 | let hex = secret_parse_hex32(hex)?; 107 | let result = StaticSecret::from(*hex); 108 | 109 | Ok(UserSecretKey(result)) 110 | } 111 | } 112 | 113 | impl Zeroize for EphemeralKey { 114 | fn zeroize(&mut self) { 115 | use std::{mem, ptr, sync::atomic}; 116 | let zeroed = EphemeralKey([0u8; 32].into()); 117 | unsafe { 118 | let ptr = self as *mut Self; 119 | ptr::write_volatile(ptr, mem::zeroed()); 120 | ptr::write_volatile(ptr, zeroed); 121 | atomic::compiler_fence(atomic::Ordering::SeqCst); 122 | } 123 | } 124 | } 125 | 126 | impl Drop for EphemeralKey { 127 | fn drop(&mut self) { 128 | self.zeroize() 129 | } 130 | } 131 | 132 | impl Zeroize for UserSecretKey { 133 | fn zeroize(&mut self) { 134 | use std::{mem, ptr, sync::atomic}; 135 | let zeroed = UserSecretKey([0u8; 32].into()); 136 | unsafe { 137 | let ptr = self as *mut Self; 138 | ptr::write_volatile(ptr, mem::zeroed()); 139 | ptr::write_volatile(ptr, zeroed); 140 | atomic::compiler_fence(atomic::Ordering::SeqCst); 141 | } 142 | } 143 | } 144 | 145 | impl Drop for UserSecretKey { 146 | fn drop(&mut self) { 147 | self.zeroize() 148 | } 149 | } 150 | --------------------------------------------------------------------------------