@@ -11,6 +11,7 @@ use std::{
1111use anyhow:: Context ;
1212use catalyst_signed_doc:: { Builder , CatalystId , CatalystSignedDocument } ;
1313use clap:: Parser ;
14+ use ed25519_dalek:: ed25519:: signature:: Signer ;
1415
1516fn main ( ) {
1617 if let Err ( err) = Cli :: parse ( ) . exec ( ) {
@@ -36,10 +37,13 @@ enum Cli {
3637 /// Path to the formed (could be empty, without any signatures) COSE document
3738 /// This exact file would be modified and new signature would be added
3839 doc : PathBuf ,
39- /// Bip32 extended secret key hex bytes (includes `chain_code`)
40+ /// secret key hex bytes
4041 sk_hex : String ,
4142 /// Signer kid
4243 kid : CatalystId ,
44+ /// provided `sk_hex` key type
45+ #[ clap( default_value_t) ]
46+ key_type : KeyType ,
4347 } ,
4448 /// Inspects Catalyst Signed Document
4549 Inspect {
@@ -53,6 +57,17 @@ enum Cli {
5357 } ,
5458}
5559
60+ /// Type of the ed25519 private signing key
61+ #[ derive( clap:: ValueEnum , Default , Clone , strum:: Display ) ]
62+ #[ strum( serialize_all = "kebab-case" ) ]
63+ enum KeyType {
64+ /// A regular ed25519
65+ #[ default]
66+ Regular ,
67+ /// A BIP32 extended ed25519
68+ Bip32Extended ,
69+ }
70+
5671impl Cli {
5772 fn exec ( self ) -> anyhow:: Result < ( ) > {
5873 match self {
@@ -71,18 +86,39 @@ impl Cli {
7186 println ! ( "report {:?}" , & signed_doc. problem_report( ) ) ;
7287 save_signed_doc ( signed_doc, & output) ?;
7388 } ,
74- Self :: Sign { doc, sk_hex, kid } => {
75- let sk = load_secret_key ( & sk_hex) ?;
89+ Self :: Sign {
90+ doc,
91+ sk_hex,
92+ kid,
93+ key_type,
94+ } => {
95+ let sk_bytes = hex:: decode ( sk_hex) ?;
7696 let cose_bytes = read_bytes_from_file ( & doc) ?;
7797 let signed_doc = signed_doc_from_bytes ( cose_bytes. as_slice ( ) ) ?;
7898
79- let new_signed_doc = signed_doc
80- . into_builder ( ) ?
81- . add_signature (
82- |message| sk. sign :: < ( ) > ( & message) . to_bytes ( ) . to_vec ( ) ,
83- kid. clone ( ) ,
84- ) ?
85- . build ( ) ?;
99+ let builder = signed_doc. into_builder ( ) ?;
100+
101+ let builder = match key_type {
102+ KeyType :: Regular => {
103+ let sk =
104+ ed25519_dalek:: SigningKey :: from_bytes ( & sk_bytes. try_into ( ) . map_err (
105+ |_| anyhow:: anyhow!( "Provided secret key must be 32 bytes long" ) ,
106+ ) ?) ;
107+ builder. add_signature (
108+ |message| sk. sign ( & message) . to_bytes ( ) . to_vec ( ) ,
109+ kid. clone ( ) ,
110+ ) ?
111+ } ,
112+ KeyType :: Bip32Extended => {
113+ let sk = ed25519_bip32:: XPrv :: from_slice_verified ( & sk_bytes) ?;
114+ builder. add_signature (
115+ |message| sk. sign :: < ( ) > ( & message) . to_bytes ( ) . to_vec ( ) ,
116+ kid. clone ( ) ,
117+ ) ?
118+ } ,
119+ } ;
120+
121+ let new_signed_doc = builder. build ( ) ?;
86122 save_signed_doc ( new_signed_doc, & doc) ?;
87123 } ,
88124 Self :: Inspect { path } => {
@@ -147,9 +183,3 @@ fn write_bytes_to_file(
147183 . write_all ( bytes)
148184 . context ( format ! ( "Failed to write to file {}" , output. display( ) ) )
149185}
150-
151- fn load_secret_key ( sk_hex : & str ) -> anyhow:: Result < ed25519_bip32:: XPrv > {
152- let sk_bytes = hex:: decode ( sk_hex) ?;
153- let sk = ed25519_bip32:: XPrv :: from_slice_verified ( & sk_bytes) ?;
154- Ok ( sk)
155- }
0 commit comments