Skip to content

Commit 8954c0d

Browse files
committed
global priority queue
1 parent 984839e commit 8954c0d

File tree

1 file changed

+48
-12
lines changed

1 file changed

+48
-12
lines changed

src/main.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::fs;
2+
use std::sync::Arc;
3+
use std::sync::Mutex;
24

35
use base64;
46
use hex::FromHexError;
@@ -66,35 +68,68 @@ impl Dec {
6668
}
6769
}
6870

71+
struct PrioQueue (Arc<Mutex<Vec<u8>>>);
72+
impl PrioQueue {
73+
pub fn new(init: Vec<u8>) -> Self {
74+
PrioQueue (Arc::new(Mutex::new(init)))
75+
}
76+
77+
pub fn prio(&self, byte: u8) {
78+
let mut q = self.0.lock().unwrap();
79+
let i = q.iter().position(|b| byte == *b).unwrap();
80+
q.remove(i);
81+
q.insert(0, byte);
82+
}
83+
84+
pub fn iter(&self) -> impl Iterator<Item = u8> {
85+
let q = self.0.lock().unwrap();
86+
q.clone().into_iter()
87+
}
88+
}
89+
6990
type Result<T, E = Error> = std::result::Result<T, E>;
7091
type DecResult = Result<Dec>;
7192

93+
/*async fn decrypt_pad<'a>(payload: &mut [u8], last: &[u8], oracle: &CmdOracle<'a>) -> Result<u8> {
94+
let blksz = payload.len() / 2;
95+
let last_last = last[blksz -1];
96+
for b in 1..blksz +1 {
97+
payload[blksz -1] = b as u8 ^ last_last;
98+
if oracle.request(&payload).await? {
99+
for i in (blksz -1) - b..blksz {
100+
payload[
101+
}
102+
return Ok(b)
103+
}
104+
}
105+
Err(Error::BraveOracle {})
106+
}*/
107+
72108
async fn decrypt_intermediate<'a>(blk: &[u8],
73109
last: &[u8],
74110
oracle: &CmdOracle<'a>,
75-
chars: [u8; 256]) -> Result<Vec<u8>> {
111+
chars: &PrioQueue,
112+
is_last: bool) -> Result<Vec<u8>> {
76113
let blksz = blk.len();
77114
let mut intermediate = vec![0; blksz];
78115
let mut payload = vec![0; blksz * 2];
79116
payload[blksz..].copy_from_slice(blk);
80-
let mut prio = chars.to_vec();
81117
for i in (0..blksz).rev() {
82118
let pad = (blksz - i) as u8;
83119
(i +1..blksz).rev().for_each(|j| payload[j] = pad ^ intermediate[j]);
84120

85121
let mut took = 0;
86-
// TODO predict based on all last chars
87-
let prio_tmp = prio.to_vec();
88-
for (j, b) in prio_tmp.iter().enumerate() {
89-
payload[i] = b ^ (last[i] ^ pad);
122+
for (j, b) in chars.iter().enumerate() {
123+
payload[i] = b ^ (pad ^ last[i]);
124+
println!("guess: {:?} / {}", std::str::from_utf8(&vec![b]), b);
90125
if oracle.request(&payload).await? {
91-
prio.remove(j);
92-
prio.insert(0, *b);
93-
took = j; break;
126+
took = j;
127+
chars.prio(b);
128+
break;
94129
}
95130
}
96131
println!("oracle took {} tries", took);
97-
ensure!(took != chars.len(), BraveOracle);
132+
ensure!(took != 255, BraveOracle);
98133
intermediate[i] = payload[i] ^ pad;
99134
}
100135

@@ -106,11 +141,12 @@ async fn decrypt<'a>(cipher: &[u8],
106141
oracle: &CmdOracle<'a>,
107142
chars: [u8; 256]) -> Result<Vec<DecResult>> {
108143
let blocks = cipher.chunks(blksz).collect::<Vec<&[u8]>>();
144+
let chars = PrioQueue::new(chars.to_vec());
109145
let i = future::join_all(blocks
110146
.iter()
111147
.skip(1)
112148
.zip(blocks[0..blocks.len() -1].iter())
113-
.map(|(blk1, blk2)| decrypt_intermediate(blk1, blk2, oracle, chars)))
149+
.map(|(blk1, blk2)| decrypt_intermediate(blk1, blk2, oracle, &chars, blk1 == blocks.last().unwrap())))
114150
.await;
115151

116152
Ok(blocks
@@ -149,7 +185,7 @@ async fn main() {
149185
.help("CBC block size"))
150186
.arg(Arg::with_name("chars")
151187
.long("chars").takes_value(true).default_value("english.chars")
152-
.long_help(concat!("space seperated list of hex encoded bytes to guess the plaintext. ",
188+
.long_help(concat!("(space seperated) list of hex encoded bytes to guess the plaintext. ",
153189
"ALL 256 POSSIBLE BYTES MUST BE PRESENT in no particular order. ",
154190
"example: 00 01 02 ... 61 62 63 ... 6A 6B ... FF FF")))
155191
.arg(Arg::with_name("oracle")

0 commit comments

Comments
 (0)