Skip to content

Commit e3ad780

Browse files
committed
Unified messages when pivot is larger than text
1 parent 83ce7c6 commit e3ad780

File tree

5 files changed

+83
-25
lines changed

5 files changed

+83
-25
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ edition = "2018"
44
name = "ptero-cli"
55
description = "A text steganography CLI tool for Social Media"
66
keywords = ["steganography", "encoding", "decoding", "text", "cli"]
7-
version = "0.4.0"
7+
version = "0.4.1"
88
license-file = "LICENSE"
99
readme = "README.md"
1010
include = [

src/cli/capacity.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ use crate::{
99
method::complex::{eluv::ELUVMethod, extended_line::ExtendedLineMethod},
1010
};
1111

12-
use super::{
13-
encoder::determine_pivot_size,
14-
progress::{new_progress_bar, spawn_progress_thread, ProgressStatus},
15-
writer::Writer,
16-
};
12+
use super::{encoder::{determine_pivot_size, validate_pivot_smaller_than_text}, progress::{new_progress_bar, spawn_progress_thread, ProgressStatus}, writer::Writer};
1713

1814
/// Calculate the minimal capacity for the cover text and given pivot
1915
#[derive(Clap)]
@@ -27,10 +23,14 @@ pub struct GetCapacityCommand {
2723
pivot: usize,
2824

2925
/// Use ELUV method for encoding.
26+
///
27+
/// Does not support different sets or variants, currently.
3028
#[clap(long, group = "method_args")]
3129
eluv: bool,
3230

3331
/// Use Extended Line method for encoding.
32+
///
33+
/// Does not support different variants, currently.
3434
#[clap(long = "eline", group = "method_args")]
3535
#[allow(dead_code)]
3636
extended_line: bool,
@@ -54,17 +54,12 @@ impl GetCapacityCommand {
5454
let mut text_fragment_count = 0;
5555

5656
let max_word_length = determine_pivot_size(cover_text.split_whitespace());
57-
let text_length = cover_text
58-
.split_whitespace()
59-
.map(|string| string.chars())
60-
.flatten()
61-
.count();
57+
validate_pivot_smaller_than_text(self.pivot, &cover_text)?;
58+
6259
debug!("Longest word in the cover text is {}", max_word_length);
6360

6461
if max_word_length > self.pivot {
6562
Writer::warn("This pivot might not guarantee the secret data will be encodable!");
66-
} else if self.pivot >= text_length {
67-
return Err("Pivot is greater than the cover text length.".into());
6863
}
6964

7065
let progress_bar = new_progress_bar(cover_text.len() as u64);
@@ -133,4 +128,21 @@ mod test {
133128
assert_eq!(result.ok(), Some(6 as u32));
134129
Ok(())
135130
}
131+
132+
133+
#[test]
134+
fn fails_when_pivot_is_too_large() -> Result<(), Box<dyn Error>> {
135+
let stego_input = "aaaaa";
136+
137+
let command = GetCapacityCommand {
138+
cover: "stub".into(),
139+
pivot: 6,
140+
eluv: false,
141+
extended_line: true,
142+
};
143+
144+
let result = command.get_cover_text_capacity(stego_input.as_bytes());
145+
assert!(result.is_err());
146+
Ok(())
147+
}
136148
}

src/cli/decoder.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ use crate::{
99
method::complex::{eluv::ELUVMethodBuilder, extended_line::ExtendedLineMethodBuilder},
1010
};
1111

12-
use super::{
13-
encoder::{get_character_set_type, ELUVCharacterSet},
14-
progress::{new_progress_bar, spawn_progress_thread, ProgressStatus},
15-
};
12+
use super::{encoder::{ELUVCharacterSet, get_character_set_type, validate_pivot_smaller_than_text}, progress::{new_progress_bar, spawn_progress_thread, ProgressStatus}};
1613

1714
/// Decode secret from the stegotext
1815
#[derive(Clap)]
@@ -82,6 +79,9 @@ impl DecodeSubCommand {
8279
let mut stego_text = String::new();
8380

8481
stego_input.read_to_string(&mut stego_text)?;
82+
83+
validate_pivot_smaller_than_text(self.pivot, &stego_text)?;
84+
8585
let decoder = self.get_method()?;
8686
info!("Using method variant {}", self.variant);
8787
let mut context = PivotByRawLineContext::new(stego_text.as_str(), self.pivot);
@@ -142,4 +142,22 @@ mod test {
142142
assert_eq!(result.ok(), Some(vec![0]));
143143
Ok(())
144144
}
145+
146+
#[test]
147+
fn fails_when_pivot_is_too_large() -> Result<(), Box<dyn Error>> {
148+
let stego_input = "aaaaa";
149+
150+
let command = DecodeSubCommand {
151+
text: "stub".into(),
152+
pivot: 6,
153+
eluv: false,
154+
extended_line: true,
155+
set: None,
156+
variant: 1,
157+
};
158+
159+
let result = command.do_decode(stego_input.as_bytes());
160+
assert!(result.is_err());
161+
Ok(())
162+
}
145163
}

src/cli/encoder.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
use std::{
2-
convert::{TryInto},
3-
error::Error,
4-
fs::File,
5-
io::Read,
6-
sync::mpsc::channel,
7-
};
1+
use std::{convert::TryInto, error::Error, fs::File, io::Read, sync::mpsc::channel};
82

93
use clap::Clap;
104
use log::{info, trace};
@@ -91,6 +85,18 @@ pub struct EncodeSubCommand {
9185
extended_line: bool,
9286
}
9387

88+
pub fn validate_pivot_smaller_than_text(
89+
pivot: usize,
90+
cover_text: &str,
91+
) -> Result<(), Box<dyn Error>> {
92+
let text_length = cover_text.len();
93+
94+
if pivot > text_length {
95+
return Err("Pivot is greater than the cover text length.".into());
96+
}
97+
Ok(())
98+
}
99+
94100
impl EncodeSubCommand {
95101
pub fn run(&self) -> Result<Vec<u8>, Box<dyn Error>> {
96102
let cover_file_input = File::open(&self.cover)?;
@@ -117,6 +123,8 @@ impl EncodeSubCommand {
117123
determine_pivot_size(cover_text.split_whitespace()),
118124
)?;
119125

126+
validate_pivot_smaller_than_text(pivot, &cover_text)?;
127+
120128
let capacity_msg = format!(
121129
"Required cover text capacity: {}",
122130
BitIterator::new(&data).count()
@@ -250,6 +258,26 @@ mod test {
250258
Ok(())
251259
}
252260

261+
#[test]
262+
fn fails_when_pivot_is_too_large() -> Result<(), Box<dyn Error>> {
263+
let cover_input = "aaaaa";
264+
let data_input: Vec<u8> = vec![0b11111111];
265+
266+
let command = EncodeSubCommand {
267+
cover: "stub".into(),
268+
data: "stub".into(),
269+
pivot: Some(6),
270+
eluv: false,
271+
extended_line: true,
272+
set: None,
273+
variant: 1,
274+
};
275+
276+
let result = command.do_encode(cover_input.as_bytes(), data_input.as_slice());
277+
assert!(result.is_err());
278+
Ok(())
279+
}
280+
253281
#[test]
254282
fn get_character_set_type_returns_default_when_none_is_provided() -> Result<(), Box<dyn Error>>
255283
{

0 commit comments

Comments
 (0)