@@ -106,6 +106,21 @@ impl SshSig {
106106 namespace : & str ,
107107 hash_alg : HashAlg ,
108108 msg : & [ u8 ] ,
109+ ) -> Result < Self > {
110+ Self :: sign_prehash (
111+ signing_key,
112+ namespace,
113+ hash_alg,
114+ hash_alg. digest ( msg) . as_slice ( ) ,
115+ )
116+ }
117+
118+ /// Sign the given prehashed message digest with the provided signing key.
119+ pub fn sign_prehash < S : SigningKey > (
120+ signing_key : & S ,
121+ namespace : & str ,
122+ hash_alg : HashAlg ,
123+ prehash : & [ u8 ] ,
109124 ) -> Result < Self > {
110125 if namespace. is_empty ( ) {
111126 return Err ( Error :: Namespace ) ;
@@ -120,13 +135,13 @@ impl SshSig {
120135 return Err ( Algorithm :: SkEcdsaSha2NistP256 . unsupported_error ( ) ) ;
121136 }
122137
123- let signed_data = Self :: signed_data ( namespace, hash_alg, msg ) ?;
138+ let signed_data = Self :: signed_data_for_prehash ( namespace, hash_alg, prehash ) ?;
124139 let signature = signing_key. try_sign ( & signed_data) ?;
125140 Self :: new ( signing_key. public_key ( ) , namespace, hash_alg, signature)
126141 }
127142
128- /// Get the raw message over which the signature for a given message
129- /// needs to be computed.
143+ /// Get the raw "enveloped" message over which the signature for a given input message is
144+ /// computed.
130145 ///
131146 /// This is a low-level function intended for uses cases which can't be
132147 /// expressed using [`SshSig::sign`], such as if the [`SigningKey`] trait
@@ -135,6 +150,20 @@ impl SshSig {
135150 /// Once a [`Signature`] has been computed over the returned byte vector,
136151 /// [`SshSig::new`] can be used to construct the final signature.
137152 pub fn signed_data ( namespace : & str , hash_alg : HashAlg , msg : & [ u8 ] ) -> Result < Vec < u8 > > {
153+ Self :: signed_data_for_prehash ( namespace, hash_alg, hash_alg. digest ( msg) . as_slice ( ) )
154+ }
155+
156+ /// Get the raw message over which the signature for a given message digest (passed as the
157+ /// `prehash` parameter) is computed.
158+ pub fn signed_data_for_prehash (
159+ namespace : & str ,
160+ hash_alg : HashAlg ,
161+ prehash : & [ u8 ] ,
162+ ) -> Result < Vec < u8 > > {
163+ if prehash. len ( ) != hash_alg. digest_size ( ) {
164+ return Err ( Error :: HashSize ) ;
165+ }
166+
138167 if namespace. is_empty ( ) {
139168 return Err ( Error :: Namespace ) ;
140169 }
@@ -143,22 +172,26 @@ impl SshSig {
143172 namespace,
144173 reserved : & [ ] ,
145174 hash_alg,
146- hash : hash_alg . digest ( msg ) . as_slice ( ) ,
175+ hash : prehash ,
147176 }
148177 . to_bytes ( )
149178 }
150179
151- /// Verify the given message against this signature.
180+ /// Verify the given prehashed message digest against this signature.
152181 ///
153182 /// Note that this method does not verify the public key or namespace
154183 /// are correct and thus is crate-private so as to ensure these parameters
155184 /// are always authenticated by users of the public API.
156- pub ( crate ) fn verify ( & self , msg : & [ u8 ] ) -> Result < ( ) > {
185+ pub ( crate ) fn verify_prehash ( & self , prehash : & [ u8 ] ) -> Result < ( ) > {
186+ if prehash. len ( ) != self . hash_alg . digest_size ( ) {
187+ return Err ( Error :: HashSize ) ;
188+ }
189+
157190 let signed_data = SignedData {
158191 namespace : self . namespace . as_str ( ) ,
159192 reserved : self . reserved . as_slice ( ) ,
160193 hash_alg : self . hash_alg ,
161- hash : self . hash_alg . digest ( msg ) . as_slice ( ) ,
194+ hash : prehash ,
162195 }
163196 . to_bytes ( ) ?;
164197
0 commit comments