@ -82,7 +82,7 @@ impl Header for KeyHeader
fn hash ( & self ) -> Sha256Hash
fn hash ( & self ) -> Sha256Hash
{
{
let mut output = Vec ::new ( ) ;
let mut output = Vec ::new ( ) ;
self . write_bytes ( & mut output , None ) . now_or_never ( ) . unwrap ( ) . expect ( "Failed to write bytes to in-memory buffer" ) ;
self . write_bytes ( & mut output , | _ | None ) . now_or_never ( ) . unwrap ( ) . expect ( "Failed to write bytes to in-memory buffer" ) ;
crypto ::sha256 ::compute_slice ( output )
crypto ::sha256 ::compute_slice ( output )
}
}
}
}
@ -135,19 +135,37 @@ impl KeyHeader
}
}
/// Write this superheader as text bytes to this stream
/// Write this superheader as text bytes to this stream
#[ instrument(err, skip(out ))]
#[ instrument(err, skip(out , passwd ))]
pub async fn write_text < T : AsyncWrite + Unpin + ? Sized > ( & self , out : & mut T , passwd : Option < & Password > ) -> Result < usize , eyre ::Report >
pub async fn write_text < T : AsyncWrite + Unpin + ? Sized , F : FnOnce ( & SaltGen ) -> Option < Password > > ( & self , out : & mut T , passwd : F ) -> Result < usize , eyre ::Report >
{
{
let text = serialise ::into_text ( self )
let salt = SaltGen ::new ( ) ;
. wrap_err_with ( | | eyre ::eyre ! ( "Failed to serialise header to text" ) )
let ( mut written , passwd ) = match passwd ( & salt ) {
Some ( passwd ) = > {
let mut salt = salt . into_inner ( ) . ok_or_else ( | | eyre ::eyre ! ( "Password function returned a password not bound to the provided salt generator" ) )
. with_warning ( | | "This is a bug, and should never happen" )
. with_section ( | | passwd . to_string ( ) . header ( "Unbound returned password was" ) ) ? ;
salt . as_mut ( ) [ 0 ] | = 1 u8 ; // make sure no conflict with NOPASS
let salt = encode_salt_to_string ( & salt ) ;
out . write_all ( salt . as_bytes ( ) ) . await ? ;
out . write_u8 ( b'\n' ) . await ? ;
debug_assert_eq! ( salt . len ( ) , TEXT_NOPASS . len ( ) ) ;
( salt . len ( ) + 1 , Some ( passwd ) )
} ,
None = > {
out . write_all ( TEXT_NOPASS ) . await ? ;
out . write_u8 ( b'\n' ) . await ? ;
( TEXT_NOPASS . len ( ) + 1 , None )
} ,
} ;
let text = if let Some ( passwd ) = passwd {
let aes = passwd . create_aes ( ) ;
serialise ::into_text_with_key_async ( self , & aes ) . await
} else {
serialise ::into_text ( self )
} . wrap_err_with ( | | eyre ::eyre ! ( "Failed to serialise header to text" ) )
. with_section ( | | format! ( "{:?}" , self ) . header ( "Header was" ) ) ? ;
. with_section ( | | format! ( "{:?}" , self ) . header ( "Header was" ) ) ? ;
let mut written = {
out . write_all ( TEXT_NOPASS ) . await ? ;
out . write_u8 ( b'\n' ) . await ? ;
TEXT_NOPASS . len ( ) + 1
} ;
for bytes in text . as_bytes ( ) . chunks ( 16 ) {
for bytes in text . as_bytes ( ) . chunks ( 16 ) {
out . write_all ( bytes ) . await ? ;
out . write_all ( bytes ) . await ? ;
out . write_u8 ( b'\n' ) . await ? ;
out . write_u8 ( b'\n' ) . await ? ;
@ -252,7 +270,7 @@ impl KeyHeader
None
None
} else {
} else {
Some ( decode_salt ( & pass_part [ .. ] )
Some ( decode_salt ( & pass_part [ .. ] )
. with_section ( move | | pass_part . header ( "Password s tring part was") ) ? )
. with_section ( move | | pass_part . header ( "Password s alt s tring part was") ) ? )
}
}
} ;
} ;
trace ! ( "Decoded hex" ) ;
trace ! ( "Decoded hex" ) ;
@ -274,14 +292,30 @@ impl KeyHeader
warn ! ( "Buffer contained no end-of-entry delimiter" ) ;
warn ! ( "Buffer contained no end-of-entry delimiter" ) ;
}
}
//let = take_one!("Expected header line");
match password {
Some ( salt ) = > {
if let Some ( salt ) = password {
match passwd ( & salt ) {
todo! ( )
Some ( passwd ) = > {
} else {
let aes = passwd . create_aes ( ) ;
Ok ::< Self , eyre ::Report > ( serialise ::from_text ( & enc [ .. ] )
. wrap_err_with ( | | eyre ::eyre ! ( "Failed to deserialise string" ) )
Ok ::< Self , eyre ::Report > ( serialise ::from_text_with_key_async ( & enc [ .. ] , & aes ) . await
. with_section ( | | enc . header ( "Read string was" ) ) ? )
. wrap_err_with ( | | eyre ::eyre ! ( "Failed to deserialise encrypted string" ) )
. with_section ( | | aes . to_string ( ) . header ( "Derived key was" ) )
. with_section ( | | salt . to_hex_string ( ) . header ( "Embedded salt was" ) )
. with_section ( | | enc . header ( "Read string was" ) )
. with_note ( | | "Did you enter the wrong password?" ) ? )
} ,
None = > return Err ( eyre ::eyre ! ( "Container is password encrypted but no password was provided" ) )
. with_section ( | | enc . header ( "Read (encrypted) string was" ) )
. with_section ( | | salt . to_hex_string ( ) . header ( "Embedded salt was" ) )
. with_note ( | | "This key must be loaded with `-p` or `-P`" ) ,
}
}
None = > {
Ok ::< Self , eyre ::Report > ( serialise ::from_text ( & enc [ .. ] )
. wrap_err_with ( | | eyre ::eyre ! ( "Failed to deserialise string" ) )
. with_section ( | | enc . header ( "Read string was" ) ) ? )
}
}
}
} ;
} ;
tokio ::pin ! ( line_sender ) ;
tokio ::pin ! ( line_sender ) ;
@ -301,8 +335,8 @@ impl KeyHeader
}
}
}
}
/// Write this key header as bytes to this stream
/// Write this key header as bytes to this stream
#[ instrument(err, skip(out ))]
#[ instrument(err, skip(out , passwd ))]
pub async fn write_bytes < T : AsyncWrite + Unpin + ? Sized > ( & self , out : & mut T , passwd : Option < & Password > ) -> Result < usize , eyre ::Report >
pub async fn write_bytes < T : AsyncWrite + Unpin + ? Sized , F : FnOnce ( & SaltGen ) -> Option < Password > > ( & self , out : & mut T , passwd : F ) -> Result < usize , eyre ::Report >
{
{
out . write_u8 ( self . kind as u8 ) . await ? ;
out . write_u8 ( self . kind as u8 ) . await ? ;
let desc = {
let desc = {
@ -361,7 +395,7 @@ impl KeyHeader
impl serialise ::BinarySerialisable for KeyHeader
impl serialise ::BinarySerialisable for KeyHeader
{
{
#[ inline(always) ] fn serialise_bytes < ' a , ' b : ' a , T : AsyncWrite + Unpin + ? Sized > ( & ' a self , out : & ' b mut T , passwd : Option < & ' b Password > ) -> LocalBoxFuture < ' a , Result < usize , eyre ::Report > >
#[ inline(always) ] fn serialise_bytes < ' a , ' b : ' a , T : AsyncWrite + Unpin + ? Sized , F : for < ' r > FnOnce ( & ' r SaltGen ) -> Option < Password > + ' b > ( & ' a self , out : & ' b mut T , passwd : F ) -> LocalBoxFuture < ' a , Result < usize , eyre ::Report > >
{
{
self . write_bytes ( out , passwd ) . boxed_local ( )
self . write_bytes ( out , passwd ) . boxed_local ( )
}
}
@ -374,7 +408,7 @@ impl serialise::BinarySerialisable for KeyHeader
impl serialise ::TextSerialiseable for KeyHeader
impl serialise ::TextSerialiseable for KeyHeader
{
{
#[ inline(always) ] fn serialise_text < ' a , ' b : ' a , T : AsyncWrite + Unpin + ? Sized > ( & ' a self , out : & ' b mut T , passwd : Option < & ' b Password > ) -> LocalBoxFuture < ' a , Result < usize , eyre ::Report > >
#[ inline(always) ] fn serialise_text < ' a , ' b : ' a , T : AsyncWrite + Unpin + ? Sized , F : for < ' r > FnOnce ( & ' r SaltGen ) -> Option < Password > + ' b > ( & ' a self , out : & ' b mut T , passwd : F ) -> LocalBoxFuture < ' a , Result < usize , eyre ::Report > >
{
{
self . write_text ( out , passwd ) . boxed_local ( )
self . write_text ( out , passwd ) . boxed_local ( )
}
}
@ -414,18 +448,22 @@ mod tests
let header = KeyHeader ::new_now ( KeyHeaderKind ::Aes , Default ::default ( ) , Default ::default ( ) ) ;
let header = KeyHeader ::new_now ( KeyHeaderKind ::Aes , Default ::default ( ) , Default ::default ( ) ) ;
let mut ser = Vec ::new ( ) ;
let mut ser = Vec ::new ( ) ;
let password = Password ::derive ( "hello world" , & Default ::default ( ) ) ;
const PASSWORD : & str = "hello world" ;
fn derive ( salt : & Salt ) -> Option < Password >
{
Some ( Password ::derive ( PASSWORD , salt ) )
}
let superheader = SuperHeader ::< KeyHeader > ::new_for ( & header ) ;
let superheader = SuperHeader ::< KeyHeader > ::new_for ( & header ) ;
println! ( "Writing: {:?} + {:?}" , superheader , header ) ;
println! ( "Writing: {:?} + {:?}" , superheader , header ) ;
let written = superheader . serialise_bytes ( & mut ser , Some ( & password ) ) . await ? +
let written = superheader . serialise_bytes ( & mut ser , | s | derive ( s . get ( ) ) ) . await ? +
header . write_bytes ( & mut ser , Some ( & password ) ) . await ? ;
header . write_bytes ( & mut ser , | s | derive ( s . get ( ) ) ) . await ? ;
println! ( "Wrote {} bytes" , written ) ;
println! ( "Wrote {} bytes" , written ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;
let mut read = & ser [ .. ] ;
let mut read = & ser [ .. ] ;
let reads = SuperHeader ::deserialise_bytes ( & mut read , | _| Some ( password . clone ( ) ) ) . await ? ;
let reads = SuperHeader ::deserialise_bytes ( & mut read , | s| derive ( s ) ) . await ? ;
println! ( "Read super: {:?}" , reads ) ;
println! ( "Read super: {:?}" , reads ) ;
let readheader = KeyHeader ::deserialise_bytes ( & mut read , | _| Some ( password . clone ( ) ) ) . await ? ;
let readheader = KeyHeader ::deserialise_bytes ( & mut read , | s| derive ( s ) ) . await ? ;
println! ( "Read real: {:?}" , readheader ) ;
println! ( "Read real: {:?}" , readheader ) ;
reads . verify_for ( & header ) ? ;
reads . verify_for ( & header ) ? ;
@ -441,7 +479,7 @@ mod tests
let header = KeyHeader ::new_now ( KeyHeaderKind ::Aes , Default ::default ( ) , Default ::default ( ) ) ;
let header = KeyHeader ::new_now ( KeyHeaderKind ::Aes , Default ::default ( ) , Default ::default ( ) ) ;
let mut ser = Vec ::new ( ) ;
let mut ser = Vec ::new ( ) ;
println! ( "Writing {:?}" , header ) ;
println! ( "Writing {:?}" , header ) ;
let val = header . write_bytes ( & mut ser , None ) . await ? ;
let val = header . write_bytes ( & mut ser , | _ | None ) . await ? ;
println! ( "Wrote {} bytes:" , val ) ;
println! ( "Wrote {} bytes:" , val ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;
@ -458,7 +496,7 @@ mod tests
let header = KeyHeader ::new_now ( KeyHeaderKind ::Aes , Default ::default ( ) , Default ::default ( ) ) ;
let header = KeyHeader ::new_now ( KeyHeaderKind ::Aes , Default ::default ( ) , Default ::default ( ) ) ;
let mut ser = Vec ::new ( ) ;
let mut ser = Vec ::new ( ) ;
println! ( "Writing {:?}" , header ) ;
println! ( "Writing {:?}" , header ) ;
let val = header . write_text ( & mut ser , None ) . await ? ;
let val = header . write_text ( & mut ser , | _ | None ) . await ? ;
println! ( "Wrote {} bytes:" , val ) ;
println! ( "Wrote {} bytes:" , val ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;
@ -477,8 +515,8 @@ mod tests
let mut ser = Vec ::new ( ) ;
let mut ser = Vec ::new ( ) ;
let superheader = SuperHeader ::< KeyHeader > ::new_for ( & header ) ;
let superheader = SuperHeader ::< KeyHeader > ::new_for ( & header ) ;
println! ( "Writing: {:?} + {:?}" , superheader , header ) ;
println! ( "Writing: {:?} + {:?}" , superheader , header ) ;
let written = superheader . write_text ( & mut ser , None ) . await ? ;
let written = superheader . write_text ( & mut ser , | _ | None ) . await ? ;
ser . extend ( header . into_memory ( serialise ::Mode ::Text , None ) ? ) ; //header.write_text(&mut ser).await?;
ser . extend ( header . into_memory ( serialise ::Mode ::Text , | _ | None ) ? ) ; //header.write_text(&mut ser).await?;
println! ( "Wrote {} bytes" , written ) ;
println! ( "Wrote {} bytes" , written ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;
println! ( "{}\n" , ser . fmt_view ( ) ) ;