Add shell scripts

master
Edward Shen 2021-10-31 02:53:43 -07:00
parent 4e0e08f3f0
commit a9e994820c
Signed by: edward
GPG Key ID: 19182661E818369F
11 changed files with 296 additions and 1 deletions

3
.gitignore vendored
View File

@ -3,4 +3,5 @@
**/dist/
**/node_modules
test.*
dist.tar.zst
dist.tar.zst
.env

1
.shellcheckrc Normal file
View File

@ -0,0 +1 @@
external-sources=true

View File

@ -2,6 +2,8 @@
set -euxo pipefail
cd "$(git rev-parse --show-toplevel)" || exit 1
# Build frontend assets
yarn
trunk build --release

22
bin/upload_test_files.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
source .env
cd "$(git rev-parse --show-toplevel)" || exit 1
cargo build --release --bin omegaupload-cli
TEST_PATH="test/*"
PADDING=0
for file in $TEST_PATH; do
if [ $PADDING -lt ${#file} ]; then
PADDING=${#file}
fi
done
for file in $TEST_PATH; do
printf "%${PADDING}s: " "${file#$TEST_PATH}"
./target/release/omegaupload-cli upload "$PASTE_URL" "$file"
done

BIN
test/archive.zip Normal file

Binary file not shown.

229
test/code.rs Normal file
View File

@ -0,0 +1,229 @@
use std::ops::{Deref, DerefMut};
use argon2::Argon2;
use chacha20poly1305::aead::generic_array::sequence::GenericSequence;
use chacha20poly1305::aead::generic_array::GenericArray;
use chacha20poly1305::aead::{AeadInPlace, NewAead};
use chacha20poly1305::XChaCha20Poly1305;
use chacha20poly1305::XNonce;
use rand::{thread_rng, Rng};
use secrecy::{ExposeSecret, Secret, SecretVec, Zeroize};
use typenum::Unsigned;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Invalid password.")]
Password,
#[error("Invalid secret key.")]
SecretKey,
#[error("An error occurred while trying to decrypt the blob.")]
Encryption,
#[error("An error occurred while trying to derive a secret key.")]
Kdf,
}
// This struct intentionally prevents implement Clone or Copy
#[derive(Default)]
pub struct Key(chacha20poly1305::Key);
impl Key {
pub fn new_secret(vec: Vec<u8>) -> Option<Secret<Self>> {
chacha20poly1305::Key::from_exact_iter(vec.into_iter())
.map(Self)
.map(Secret::new)
}
}
impl AsRef<chacha20poly1305::Key> for Key {
fn as_ref(&self) -> &chacha20poly1305::Key {
&self.0
}
}
impl Deref for Key {
type Target = chacha20poly1305::Key;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Key {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Zeroize for Key {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
/// Seals the provided message with an optional message. The resulting sealed
/// message has the nonce used to encrypt the message appended to it as well as
/// a salt string used to derive the key. In other words, the modified buffer is
/// one of the following to possibilities, depending if there was a password
/// provided:
///
/// ```
/// modified = C(message, rng_key, nonce) || nonce
/// ```
/// or
/// ```
/// modified = C(C(message, rng_key, nonce), kdf(pw, salt), nonce + 1) || nonce || salt
/// ```
///
/// Where:
/// - `C(message, key, nonce)` represents encrypting a provided message with
/// `XChaCha20Poly1305`.
/// - `rng_key` represents a randomly generated key.
/// - `kdf(pw, salt)` represents a key derived from Argon2.
pub fn seal_in_place(
message: &mut Vec<u8>,
pw: Option<SecretVec<u8>>,
) -> Result<Secret<Key>, Error> {
let (key, nonce) = gen_key_nonce();
let cipher = XChaCha20Poly1305::new(key.expose_secret());
cipher
.encrypt_in_place(&nonce, &[], message)
.map_err(|_| Error::Encryption)?;
let mut maybe_salt_string = None;
if let Some(password) = pw {
let (key, salt_string) = kdf(&password).map_err(|_| Error::Kdf)?;
maybe_salt_string = Some(salt_string);
let cipher = XChaCha20Poly1305::new(key.expose_secret());
cipher
.encrypt_in_place(&nonce.increment(), &[], message)
.map_err(|_| Error::Encryption)?;
}
message.extend_from_slice(nonce.as_slice());
if let Some(maybe_salted_string) = maybe_salt_string {
message.extend_from_slice(maybe_salted_string.as_ref());
}
Ok(key)
}
pub fn open_in_place(
data: &mut Vec<u8>,
key: &Secret<Key>,
password: Option<SecretVec<u8>>,
) -> Result<(), Error> {
let pw_key = if let Some(password) = password {
let salt_buf = data.split_off(data.len() - Salt::SIZE);
let argon = Argon2::default();
let mut pw_key = Key::default();
argon
.hash_password_into(password.expose_secret(), &salt_buf, &mut pw_key)
.map_err(|_| Error::Kdf)?;
Some(Secret::new(pw_key))
} else {
None
};
let nonce = Nonce::from_slice(&data.split_off(data.len() - Nonce::SIZE));
// At this point we should have a buffer that's only the ciphertext.
if let Some(key) = pw_key {
let cipher = XChaCha20Poly1305::new(key.expose_secret());
cipher
.decrypt_in_place(&nonce.increment(), &[], data)
.map_err(|_| Error::Password)?;
}
let cipher = XChaCha20Poly1305::new(key.expose_secret());
cipher
.decrypt_in_place(&nonce, &[], data)
.map_err(|_| Error::SecretKey)?;
Ok(())
}
/// Securely generates a random key and nonce.
#[must_use]
fn gen_key_nonce() -> (Secret<Key>, Nonce) {
let mut rng = thread_rng();
let mut key = GenericArray::default();
rng.fill(key.as_mut_slice());
let mut nonce = Nonce::default();
rng.fill(nonce.as_mut_slice());
(Secret::new(Key(key)), nonce)
}
// Type alias; to ensure that we're consistent on what the inner impl is.
type NonceImpl = XNonce;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
struct Nonce(NonceImpl);
impl Default for Nonce {
fn default() -> Self {
Self(GenericArray::default())
}
}
impl Deref for Nonce {
type Target = NonceImpl;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Nonce {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl AsRef<[u8]> for Nonce {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl Nonce {
const SIZE: usize = <NonceImpl as GenericSequence<_>>::Length::USIZE;
#[must_use]
pub fn increment(&self) -> Self {
let mut inner = self.0;
inner.as_mut_slice()[0] += 1;
Self(inner)
}
#[must_use]
pub fn from_slice(slice: &[u8]) -> Self {
Self(*NonceImpl::from_slice(slice))
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
struct Salt([u8; Self::SIZE]);
impl Salt {
const SIZE: usize = argon2::password_hash::Salt::RECOMMENDED_LENGTH;
fn random() -> Self {
let mut salt = [0_u8; Self::SIZE];
thread_rng().fill(&mut salt);
Self(salt)
}
}
impl AsRef<[u8]> for Salt {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
/// Hashes an input to output a usable key.
fn kdf(password: &SecretVec<u8>) -> Result<(Secret<Key>, Salt), argon2::Error> {
let salt = Salt::random();
let hasher = Argon2::default();
let mut key = Key::default();
hasher.hash_password_into(password.expose_secret().as_ref(), salt.as_ref(), &mut key)?;
Ok((Secret::new(key), salt))
}

BIN
test/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

21
test/image.svg Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 4417 3259" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<g transform="matrix(4.16667,0,0,4.16667,0,0)">
<path d="M525.403,293.05C393.77,293.05 274.175,308.875 185.633,334.665L185.633,554.963C274.175,580.753 393.77,596.577 525.403,596.577C676.06,596.577 810.938,575.848 901.537,543.175L901.537,346.457C810.938,313.781 676.06,293.05 525.403,293.05Z" style="fill:rgb(143,30,28);fill-rule:nonzero;"/>
<path d="M907.423,492.442C903.566,481.779 902.794,468.288 906.062,455.28C911.912,431.991 928.483,419.082 943.075,426.447C946.693,428.274 949.849,431.178 952.462,434.865C952.701,434.864 952.94,434.865 953.177,434.881C953.177,434.881 997.729,487.987 956.49,550.884C955.595,554.453 879.956,642.602 862.447,645.408C850.987,647.244 877.338,555.41 907.423,492.442Z" style="fill:rgb(143,30,28);fill-rule:nonzero;"/>
<path d="M176.479,482.021C181.779,472.391 183.637,459.233 180.696,445.596C175.43,421.18 156.786,404.486 139.054,408.311C134.656,409.259 130.729,411.383 127.388,414.409C127.106,414.351 126.824,414.296 126.543,414.256C126.543,414.256 70.251,456.208 114.486,528.18C115.291,531.921 198.337,637.018 218.797,643.943C232.188,648.475 207.55,551.418 176.479,482.021Z" style="fill:rgb(143,30,28);fill-rule:nonzero;"/>
<path d="M97.467,488.066L97.474,488.081C97.659,488.226 97.831,488.357 97.467,488.066Z" style="fill:rgb(227,58,37);fill-rule:nonzero;"/>
<path d="M993.119,412.903C992.239,409.839 991.363,406.777 990.457,403.741L1021.14,359.29C1024.27,354.768 1024.91,348.892 1022.87,343.735C1020.83,338.605 1016.38,334.925 1011.11,334.025L959.224,325.22C957.216,321.118 955.108,317.078 952.994,313.07L974.791,263.167C977.034,258.08 976.56,252.172 973.588,247.559C970.627,242.923 965.598,240.215 960.239,240.426L907.583,242.339C904.856,238.789 902.087,235.271 899.261,231.818L911.362,178.328C912.587,172.895 911.04,167.21 907.259,163.264C903.497,159.332 898.03,157.705 892.833,158.981L841.544,171.589C838.223,168.654 834.845,165.756 831.43,162.916L833.278,108.002C833.476,102.443 830.885,97.161 826.434,94.077C821.988,90.973 816.341,90.504 811.478,92.811L763.631,115.558C759.777,113.348 755.903,111.158 751.987,109.041L743.532,54.926C742.675,49.444 739.147,44.788 734.206,42.661C729.283,40.523 723.638,41.213 719.315,44.469L676.656,76.476C672.456,75.08 668.237,73.743 663.964,72.465L645.578,21.148C643.708,15.919 639.397,12.077 634.14,10.997C628.901,9.926 623.51,11.74 619.877,15.799L583.97,55.971C579.628,55.471 575.285,55.015 570.927,54.639L543.204,7.926C540.394,3.194 535.434,0.314 530.088,0.314C524.754,0.314 519.784,3.194 516.998,7.926L489.265,54.639C484.907,55.015 480.543,55.471 476.209,55.971L440.299,15.799C436.663,11.74 431.252,9.926 426.031,10.997C420.776,12.089 416.458,15.919 414.598,21.148L396.196,72.465C391.936,73.743 387.715,75.092 383.505,76.476L340.861,44.469C336.525,41.203 330.881,40.514 325.945,42.661C321.026,44.788 317.484,49.444 316.632,54.926L308.171,109.041C304.257,111.158 300.382,113.335 296.518,115.558L248.676,92.811C243.818,90.496 238.147,90.973 233.722,94.077C229.277,97.161 226.68,102.443 226.882,108.002L228.717,162.916C225.312,165.756 221.943,168.654 218.605,171.589L167.326,158.981C162.115,157.716 156.656,159.332 152.885,163.264C149.09,167.21 147.553,172.895 148.772,178.328L160.851,231.818C158.049,235.285 155.276,238.789 152.558,242.339L99.903,240.426C94.588,240.269 89.516,242.923 86.547,247.559C83.572,252.172 83.122,258.08 85.336,263.167L107.15,313.07C105.031,317.078 102.926,321.118 100.901,325.22L49.018,334.025C43.747,334.913 39.304,338.591 37.254,343.735C35.217,348.892 35.878,354.768 38.989,359.29L69.679,403.741C69.442,404.525 69.224,405.317 68.989,406.105L52.126,424.017L97.467,488.066C97.467,488.066 532.619,688.798 936.264,491.462C982.372,483.189 993.119,412.903 993.119,412.903Z" style="fill:rgb(228,58,37);fill-rule:nonzero;"/>
<path d="M608.303,376.759C608.303,376.759 656.46,324.03 704.618,376.759C704.618,376.759 742.458,447.071 704.618,482.222C704.618,482.222 642.701,531.439 608.303,482.222C608.303,482.222 567.024,443.55 608.303,376.759Z" style="fill:rgb(3,4,4);fill-rule:nonzero;"/>
<path d="M664.057,396.32C664.057,416.853 651.954,433.499 637.027,433.499C622.103,433.499 610,416.853 610,396.32C610,375.788 622.103,359.14 637.027,359.14C651.954,359.14 664.057,375.788 664.057,396.32Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M393.365,362.361C393.365,362.361 475.973,325.785 498.519,407.423C498.519,407.423 522.137,502.577 430.682,507.948C430.682,507.948 314.06,485.486 393.365,362.361Z" style="fill:rgb(3,4,4);fill-rule:nonzero;"/>
<path d="M434.855,397.668C434.855,418.841 422.375,436.014 406.978,436.014C391.587,436.014 379.104,418.841 379.104,397.668C379.104,376.49 391.587,359.322 406.978,359.322C422.375,359.322 434.855,376.49 434.855,397.668Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M111.602,499.216C122.569,486.753 149.213,471.659 147.172,452.934C143.519,419.407 115.716,394.935 85.073,398.275C77.473,399.103 70.415,401.567 64.149,405.311C63.687,405.204 63.224,405.1 62.761,405.017C62.761,405.017 -40.87,455.89 18.197,557.674C18.754,562.811 136.045,713.342 168.985,724.805C190.544,732.307 149.074,596.165 111.602,499.216Z" style="fill:rgb(228,58,37);fill-rule:nonzero;"/>
<path d="M953.549,494.673C940.856,483.973 907.387,474.255 906.629,455.435C905.273,421.737 929.141,393.414 959.941,392.175C967.579,391.867 974.925,393.258 981.676,396.032C982.118,395.858 982.56,395.686 983.005,395.535C983.005,395.535 1093.03,430.486 1049.7,539.901C1049.91,545.064 956.232,711.317 925.355,727.536C905.146,738.151 930.861,596.105 953.549,494.673Z" style="fill:rgb(228,58,37);fill-rule:nonzero;"/>
<path d="M191.142,495.558C191.142,495.558 189.759,632.854 324.308,663.49L352.362,607.127C352.362,607.127 254.867,616.558 247.367,495.558L191.142,495.558Z" style="fill:rgb(228,58,37);fill-rule:nonzero;"/>
<path d="M876.362,495.558C876.362,495.558 877.744,632.854 743.195,663.49L715.141,607.127C715.141,607.127 812.636,616.558 820.136,495.558L876.362,495.558Z" style="fill:rgb(228,58,37);fill-rule:nonzero;"/>
<path d="M779.167,635.591C758.917,586.649 693.572,567.218 633.216,592.191C580.09,614.172 548.579,663.223 555.592,708.036C597.538,707.384 642.532,704.665 686.328,698.318C686.328,698.318 660.491,740.081 622.471,776.529C648.037,783.128 677.854,781.297 706.547,769.425C766.904,744.452 799.417,684.532 779.167,635.591Z" style="fill:rgb(228,58,37);fill-rule:nonzero;"/>
<path d="M404.746,695.984C404.746,695.984 459.949,703.279 535.416,705.14C542.026,657.629 506.036,607.348 448.615,587.897C385.177,566.409 319.626,590.689 302.201,642.129C284.776,693.569 322.077,752.689 385.515,774.178C413.636,783.704 442.168,784.227 466.744,777.385C429.833,740.88 404.746,695.984 404.746,695.984Z" style="fill:rgb(228,58,37);fill-rule:nonzero;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
test/movie.mp4 Normal file

Binary file not shown.

BIN
test/music.mp3 Normal file

Binary file not shown.

19
test/text.txt Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2021 Edward Shen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.