11use std:: fs;
2+ use std:: sync:: Arc ;
3+ use std:: sync:: Mutex ;
24
35use base64;
46use 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+
6990type Result < T , E = Error > = std:: result:: Result < T , E > ;
7091type 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+
72108async 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