Skip to content

Commit ea896d2

Browse files
committed
Implement MultiPartSigner/Verifier for ECDSA
1 parent 5f92081 commit ea896d2

File tree

3 files changed

+144
-12
lines changed

3 files changed

+144
-12
lines changed

ecdsa/src/recovery.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use {
77
crate::{SigningKey, hazmat::sign_prehashed_rfc6979},
88
elliptic_curve::{FieldBytes, subtle::CtOption},
99
signature::{
10-
DigestSigner, RandomizedDigestSigner, Signer,
10+
DigestSigner, MultiPartSigner, RandomizedDigestSigner, Signer,
1111
digest::FixedOutput,
1212
hazmat::{PrehashSigner, RandomizedPrehashSigner},
1313
rand_core::TryCryptoRng,
@@ -291,7 +291,21 @@ where
291291
SignatureSize<C>: ArraySize,
292292
{
293293
fn try_sign(&self, msg: &[u8]) -> Result<(Signature<C>, RecoveryId)> {
294-
self.sign_recoverable(msg)
294+
self.try_multi_part_sign(&[msg])
295+
}
296+
}
297+
298+
#[cfg(feature = "signing")]
299+
impl<C> MultiPartSigner<(Signature<C>, RecoveryId)> for SigningKey<C>
300+
where
301+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
302+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
303+
SignatureSize<C>: ArraySize,
304+
{
305+
fn try_multi_part_sign(&self, msg: &[&[u8]]) -> Result<(Signature<C>, RecoveryId)> {
306+
let mut digest = C::Digest::new();
307+
msg.iter().for_each(|slice| digest.update(slice));
308+
self.sign_digest_recoverable(digest)
295309
}
296310
}
297311

ecdsa/src/signing.rs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use elliptic_curve::{
1515
zeroize::{Zeroize, ZeroizeOnDrop},
1616
};
1717
use signature::{
18-
DigestSigner, RandomizedDigestSigner, RandomizedSigner, Signer,
18+
DigestSigner, MultiPartSigner, RandomizedDigestSigner, RandomizedMultiPartSigner,
19+
RandomizedSigner, Signer,
1920
hazmat::{PrehashSigner, RandomizedPrehashSigner},
2021
rand_core::{CryptoRng, TryCryptoRng},
2122
};
@@ -176,7 +177,20 @@ where
176177
SignatureSize<C>: ArraySize,
177178
{
178179
fn try_sign(&self, msg: &[u8]) -> Result<Signature<C>> {
179-
self.try_sign_digest(C::Digest::new_with_prefix(msg))
180+
self.try_multi_part_sign(&[msg])
181+
}
182+
}
183+
184+
impl<C> MultiPartSigner<Signature<C>> for SigningKey<C>
185+
where
186+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
187+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
188+
SignatureSize<C>: ArraySize,
189+
{
190+
fn try_multi_part_sign(&self, msg: &[&[u8]]) -> core::result::Result<Signature<C>, Error> {
191+
let mut digest = C::Digest::new();
192+
msg.iter().for_each(|slice| digest.update(slice));
193+
self.try_sign_digest(digest)
180194
}
181195
}
182196

@@ -234,7 +248,25 @@ where
234248
rng: &mut R,
235249
msg: &[u8],
236250
) -> Result<Signature<C>> {
237-
self.try_sign_digest_with_rng(rng, C::Digest::new_with_prefix(msg))
251+
self.try_multi_part_sign_with_rng(rng, &[msg])
252+
}
253+
}
254+
255+
impl<C> RandomizedMultiPartSigner<Signature<C>> for SigningKey<C>
256+
where
257+
Self: RandomizedDigestSigner<C::Digest, Signature<C>>,
258+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
259+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
260+
SignatureSize<C>: ArraySize,
261+
{
262+
fn try_multi_part_sign_with_rng<R: TryCryptoRng + ?Sized>(
263+
&self,
264+
rng: &mut R,
265+
msg: &[&[u8]],
266+
) -> Result<Signature<C>> {
267+
let mut digest = C::Digest::new();
268+
msg.iter().for_each(|slice| digest.update(slice));
269+
self.try_sign_digest_with_rng(rng, digest)
238270
}
239271
}
240272

@@ -260,7 +292,21 @@ where
260292
SignatureSize<C>: ArraySize,
261293
{
262294
fn try_sign(&self, msg: &[u8]) -> Result<SignatureWithOid<C>> {
263-
self.try_sign_digest(C::Digest::new_with_prefix(msg))
295+
self.try_multi_part_sign(&[msg])
296+
}
297+
}
298+
299+
impl<C> MultiPartSigner<SignatureWithOid<C>> for SigningKey<C>
300+
where
301+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
302+
C::Digest: AssociatedOid,
303+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
304+
SignatureSize<C>: ArraySize,
305+
{
306+
fn try_multi_part_sign(&self, msg: &[&[u8]]) -> Result<SignatureWithOid<C>> {
307+
let mut digest = C::Digest::new();
308+
msg.iter().for_each(|slice| digest.update(slice));
309+
self.try_sign_digest(digest)
264310
}
265311
}
266312

@@ -364,6 +410,25 @@ where
364410
}
365411
}
366412

413+
#[cfg(feature = "der")]
414+
impl<C> RandomizedMultiPartSigner<der::Signature<C>> for SigningKey<C>
415+
where
416+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
417+
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
418+
SignatureSize<C>: ArraySize,
419+
der::MaxSize<C>: ArraySize,
420+
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArraySize,
421+
{
422+
fn try_multi_part_sign_with_rng<R: TryCryptoRng + ?Sized>(
423+
&self,
424+
rng: &mut R,
425+
msg: &[&[u8]],
426+
) -> Result<der::Signature<C>> {
427+
RandomizedMultiPartSigner::<Signature<C>>::try_multi_part_sign_with_rng(self, rng, msg)
428+
.map(Into::into)
429+
}
430+
}
431+
367432
//
368433
// Other trait impls
369434
//

ecdsa/src/verifying.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use elliptic_curve::{
1313
sec1::{self, CompressedPoint, EncodedPoint, FromEncodedPoint, ToEncodedPoint},
1414
};
1515
use signature::{
16-
DigestVerifier, Verifier,
16+
DigestVerifier, MultiPartVerifier, Verifier,
1717
digest::{Digest, FixedOutput},
1818
hazmat::PrehashVerifier,
1919
};
@@ -178,7 +178,19 @@ where
178178
SignatureSize<C>: ArraySize,
179179
{
180180
fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<()> {
181-
self.verify_digest(C::Digest::new_with_prefix(msg), signature)
181+
self.multi_part_verify(&[msg], signature)
182+
}
183+
}
184+
185+
impl<C> MultiPartVerifier<Signature<C>> for VerifyingKey<C>
186+
where
187+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
188+
SignatureSize<C>: ArraySize,
189+
{
190+
fn multi_part_verify(&self, msg: &[&[u8]], signature: &Signature<C>) -> Result<()> {
191+
let mut digest = C::Digest::new();
192+
msg.iter().for_each(|slice| digest.update(slice));
193+
self.verify_digest(digest, signature)
182194
}
183195
}
184196

@@ -189,11 +201,38 @@ where
189201
SignatureSize<C>: ArraySize,
190202
{
191203
fn verify(&self, msg: &[u8], sig: &SignatureWithOid<C>) -> Result<()> {
204+
self.multi_part_verify(&[msg], sig)
205+
}
206+
}
207+
208+
#[cfg(feature = "sha2")]
209+
impl<C> MultiPartVerifier<SignatureWithOid<C>> for VerifyingKey<C>
210+
where
211+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
212+
SignatureSize<C>: ArraySize,
213+
{
214+
fn multi_part_verify(&self, msg: &[&[u8]], sig: &SignatureWithOid<C>) -> Result<()> {
192215
match sig.oid() {
193-
ECDSA_SHA224_OID => self.verify_prehash(&Sha224::digest(msg), sig.signature()),
194-
ECDSA_SHA256_OID => self.verify_prehash(&Sha256::digest(msg), sig.signature()),
195-
ECDSA_SHA384_OID => self.verify_prehash(&Sha384::digest(msg), sig.signature()),
196-
ECDSA_SHA512_OID => self.verify_prehash(&Sha512::digest(msg), sig.signature()),
216+
ECDSA_SHA224_OID => {
217+
let mut digest = Sha224::new();
218+
msg.iter().for_each(|slice| digest.update(slice));
219+
self.verify_prehash(&digest.finalize(), sig.signature())
220+
}
221+
ECDSA_SHA256_OID => {
222+
let mut digest = Sha256::new();
223+
msg.iter().for_each(|slice| digest.update(slice));
224+
self.verify_prehash(&digest.finalize(), sig.signature())
225+
}
226+
ECDSA_SHA384_OID => {
227+
let mut digest = Sha384::new();
228+
msg.iter().for_each(|slice| digest.update(slice));
229+
self.verify_prehash(&digest.finalize(), sig.signature())
230+
}
231+
ECDSA_SHA512_OID => {
232+
let mut digest = Sha512::new();
233+
msg.iter().for_each(|slice| digest.update(slice));
234+
self.verify_prehash(&digest.finalize(), sig.signature())
235+
}
197236
_ => Err(Error::new()),
198237
}
199238
}
@@ -242,6 +281,20 @@ where
242281
}
243282
}
244283

284+
#[cfg(feature = "der")]
285+
impl<C> MultiPartVerifier<der::Signature<C>> for VerifyingKey<C>
286+
where
287+
C: EcdsaCurve + CurveArithmetic + DigestPrimitive,
288+
SignatureSize<C>: ArraySize,
289+
der::MaxSize<C>: ArraySize,
290+
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArraySize,
291+
{
292+
fn multi_part_verify(&self, msg: &[&[u8]], signature: &der::Signature<C>) -> Result<()> {
293+
let signature = Signature::<C>::try_from(signature.clone())?;
294+
MultiPartVerifier::<Signature<C>>::multi_part_verify(self, msg, &signature)
295+
}
296+
}
297+
245298
//
246299
// Other trait impls
247300
//

0 commit comments

Comments
 (0)