11use std:: time:: Duration ;
22
3+ use byteorder:: { BigEndian , WriteBytesExt } ;
34use failure:: Error ;
45use nom:: { be_u16, be_u8, ErrorKind , IResult } ;
56use nom:: Err as NomErr ;
@@ -239,6 +240,41 @@ impl Key {
239240
240241 Ok ( key)
241242 }
243+
244+ pub fn to_bytes ( & self ) -> Result < Vec < u8 > , Error > {
245+ let mut out = Vec :: new ( ) ;
246+
247+ out. push ( 4u8 ) ;
248+ out. write_u32 :: < BigEndian > ( self . creation_time . as_secs ( ) as u32 ) ?;
249+ out. push ( self . pubkey_algorithm as u8 ) ;
250+ out. extend ( & self . key_material . public_to_bytes ( ) ?) ;
251+
252+ let private_bytes = self . key_material . private_to_bytes ( ) ?;
253+ if !private_bytes. is_empty ( ) {
254+ match self . encryption_method {
255+ None => bail ! ( KeyError :: InvalidEncryption ) ,
256+ Some ( KeyEncryptionMethod :: Unencrypted ) => {
257+ out. push ( 0u8 ) ;
258+ match self . privkey_checksum {
259+ None => bail ! ( KeyError :: BadChecksum ) ,
260+ Some ( ref checksum) => {
261+ out. extend ( & private_bytes) ;
262+ out. extend ( checksum) ;
263+ }
264+ }
265+ }
266+ Some ( ref e) => bail ! ( KeyError :: UnimplementedEncryption {
267+ method: format!( "{:?}" , e) ,
268+ } )
269+ }
270+ }
271+
272+ Ok ( out)
273+ }
274+
275+ pub fn expiration_time ( & self ) -> Option < Duration > {
276+ self . expiration_time
277+ }
242278}
243279
244280#[ derive( Clone , Debug ) ]
@@ -248,6 +284,71 @@ pub enum KeyMaterial {
248284 Elgamal ( ElgamalPublicKey , Option < ElgamalPrivateKey > ) ,
249285}
250286
287+ impl KeyMaterial {
288+ pub fn public_to_bytes ( & self ) -> Result < Vec < u8 > , Error > {
289+ let mut out = Vec :: new ( ) ;
290+
291+ match self {
292+ & KeyMaterial :: Rsa ( ref public, _) => {
293+ out. write_u16 :: < BigEndian > ( public. n . bits ( ) as u16 ) ?;
294+ out. extend ( & public. n . to_bytes_be ( ) ) ;
295+ out. write_u16 :: < BigEndian > ( public. e . bits ( ) as u16 ) ?;
296+ out. extend ( & public. e . to_bytes_be ( ) ) ;
297+ }
298+ & KeyMaterial :: Dsa ( ref public, _) => {
299+ out. write_u16 :: < BigEndian > ( public. p . bits ( ) as u16 ) ?;
300+ out. extend ( & public. p . to_bytes_be ( ) ) ;
301+ out. write_u16 :: < BigEndian > ( public. q . bits ( ) as u16 ) ?;
302+ out. extend ( & public. q . to_bytes_be ( ) ) ;
303+ out. write_u16 :: < BigEndian > ( public. g . bits ( ) as u16 ) ?;
304+ out. extend ( & public. g . to_bytes_be ( ) ) ;
305+ out. write_u16 :: < BigEndian > ( public. y . bits ( ) as u16 ) ?;
306+ out. extend ( & public. y . to_bytes_be ( ) ) ;
307+ }
308+ & KeyMaterial :: Elgamal ( ref public, _) => {
309+ out. write_u16 :: < BigEndian > ( public. p . bits ( ) as u16 ) ?;
310+ out. extend ( & public. p . to_bytes_be ( ) ) ;
311+ out. write_u16 :: < BigEndian > ( public. g . bits ( ) as u16 ) ?;
312+ out. extend ( & public. g . to_bytes_be ( ) ) ;
313+ out. write_u16 :: < BigEndian > ( public. y . bits ( ) as u16 ) ?;
314+ out. extend ( & public. y . to_bytes_be ( ) ) ;
315+ }
316+ }
317+
318+ Ok ( out)
319+ }
320+
321+ pub fn private_to_bytes ( & self ) -> Result < Vec < u8 > , Error > {
322+ let mut out = Vec :: new ( ) ;
323+
324+ match self {
325+ & KeyMaterial :: Rsa ( _, Some ( ref private) ) => {
326+ out. write_u16 :: < BigEndian > ( private. d . bits ( ) as u16 ) ?;
327+ out. extend ( & private. d . to_bytes_be ( ) ) ;
328+ out. write_u16 :: < BigEndian > ( private. p . bits ( ) as u16 ) ?;
329+ out. extend ( & private. p . to_bytes_be ( ) ) ;
330+ out. write_u16 :: < BigEndian > ( private. q . bits ( ) as u16 ) ?;
331+ out. extend ( & private. q . to_bytes_be ( ) ) ;
332+ out. write_u16 :: < BigEndian > ( private. u . bits ( ) as u16 ) ?;
333+ out. extend ( & private. u . to_bytes_be ( ) ) ;
334+ }
335+ & KeyMaterial :: Dsa ( _, Some ( DsaPrivateKey ( ref private) ) ) => {
336+ out. write_u16 :: < BigEndian > ( private. bits ( ) as u16 ) ?;
337+ out. extend ( & private. to_bytes_be ( ) ) ;
338+ }
339+ & KeyMaterial :: Elgamal ( _, Some ( ElgamalPrivateKey ( ref private) ) ) => {
340+ out. write_u16 :: < BigEndian > ( private. bits ( ) as u16 ) ?;
341+ out. extend ( & private. to_bytes_be ( ) ) ;
342+ }
343+ & KeyMaterial :: Rsa ( _, None )
344+ | & KeyMaterial :: Dsa ( _, None )
345+ | & KeyMaterial :: Elgamal ( _, None ) => { }
346+ }
347+
348+ Ok ( out)
349+ }
350+ }
351+
251352#[ derive( Clone , Debug ) ]
252353pub enum KeyEncryptionMethod {
253354 Unencrypted ,
@@ -295,6 +396,12 @@ pub struct ElgamalPrivateKey(BigUint);
295396pub enum KeyError {
296397 #[ fail( display = "Invalid key format: {}" , reason) ]
297398 InvalidFormat { reason : String } ,
399+ #[ fail( display = "Invalid/no encryption set" ) ]
400+ InvalidEncryption ,
401+ #[ fail( display = "Bad checksum" ) ]
402+ BadChecksum ,
403+ #[ fail( display = "Unimplemented key encryption method: {}" , method) ]
404+ UnimplementedEncryption { method : String } ,
298405 #[ fail( display = "Malformed MPI payload" ) ]
299406 MalformedMpi ,
300407}
0 commit comments