Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signature for pre-hashed messages (slice input) #525

Closed
davxy opened this issue Feb 17, 2022 · 2 comments
Closed

Signature for pre-hashed messages (slice input) #525

davxy opened this issue Feb 17, 2022 · 2 comments

Comments

@davxy
Copy link

davxy commented Feb 17, 2022

I'm struggling understanding how I can sign a byte array (or a slice) containing an already hashed message.

Given that I have a byte array containing a 32 bytes hash, I would like to perform something like:

let hash_buf = [0u8; 32];
let signing_key = SigningKey::random(&mut OsRng);
let sig: recoverable::Signature = signing_key.sign_digest_buf(&hash_buf);

I see that there is the signing_key.sign_digest(). But that is not what I want since I don't have a Digest implementation here.

Thank you

@tarcieri
Copy link
Member

This is a somewhat dangerous API in that failure to use a hash function on the input message can lead to arbitrary signature forgeries. For that reason we do not provide a high-level interface to it.

If you really, really need such an API, you'll need to use the low-level SignPrimitive API:

https://docs.rs/ecdsa/latest/ecdsa/hazmat/trait.SignPrimitive.html

You can compute a scalar from a known existing digest using <Scalar as Reduce<U256>>::from_be_bytes. See the implementation of DigestSigner as an example:

https://docs.rs/ecdsa/latest/src/ecdsa/sign.rs.html#179-181

@davxy
Copy link
Author

davxy commented Feb 18, 2022

I managed to have something working.

This is a reference for who tries to do something similar:

use ecdsa::{
    elliptic_curve::{
        generic_array::{typenum::U32, GenericArray},
        ops::Reduce,
    },
    hazmat::{rfc6979_generate_k, SignPrimitive},
    signature::PrehashSignature,
    RecoveryId,
};
use k256::{
    ecdsa::{Signature, SigningKey},
    NonZeroScalar, Scalar, U256,
};
use rand::rngs::OsRng;

fn sign_prehashed(hash: [u8; 32]) -> (Signature, Option<RecoveryId>) {
    let signing_key = SigningKey::random(&mut OsRng);

    let hash_array: GenericArray<u8, U32> = GenericArray::from_slice(&hash).clone();
    let hash_scalar = <Scalar as Reduce<U256>>::from_be_bytes_reduced(hash_array);

    let priv_bytes = signing_key.to_bytes();
    let priv_scalar = <NonZeroScalar as Reduce<U256>>::from_be_bytes_reduced(priv_bytes);

    let k = rfc6979_generate_k::<_, <Signature as PrehashSignature>::Digest>(
        &priv_scalar,
        &hash_scalar,
        &[],
    );

    priv_scalar.try_sign_prehashed(**k, hash_scalar).unwrap()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants