mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 23:31:07 +00:00
Add CryptoStore::ecdsa_sign_prehashed() (#8838)
* Pair::sign_prehashed() * add CryptoStore::ecdsa_sign_prehashed() * add test for testing keystore * address review comments
This commit is contained in:
@@ -142,6 +142,15 @@ impl CryptoStore for LocalKeystore {
|
||||
) -> std::result::Result<Option<VRFSignature>, TraitError> {
|
||||
SyncCryptoStore::sr25519_vrf_sign(self, key_type, public, transcript_data)
|
||||
}
|
||||
|
||||
async fn ecdsa_sign_prehashed(
|
||||
&self,
|
||||
id: KeyTypeId,
|
||||
public: &ecdsa::Public,
|
||||
msg: &[u8; 32],
|
||||
) -> std::result::Result<Option<ecdsa::Signature>, TraitError> {
|
||||
SyncCryptoStore::ecdsa_sign_prehashed(self, id, public, msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl SyncCryptoStore for LocalKeystore {
|
||||
@@ -301,6 +310,18 @@ impl SyncCryptoStore for LocalKeystore {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn ecdsa_sign_prehashed(
|
||||
&self,
|
||||
id: KeyTypeId,
|
||||
public: &ecdsa::Public,
|
||||
msg: &[u8; 32],
|
||||
) -> std::result::Result<Option<ecdsa::Signature>, TraitError> {
|
||||
let pair = self.0.read()
|
||||
.key_pair_by_type::<ecdsa::Pair>(public, id)?;
|
||||
|
||||
pair.map(|k| k.sign_prehashed(msg)).map(Ok).transpose()
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<SyncCryptoStorePtr> for LocalKeystore {
|
||||
|
||||
@@ -531,6 +531,12 @@ impl Pair {
|
||||
Self::from_seed(&padded_seed)
|
||||
})
|
||||
}
|
||||
|
||||
/// Sign a pre-hashed message
|
||||
pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature {
|
||||
let message = secp256k1::Message::parse(message);
|
||||
secp256k1::sign(&message, &self.secret).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl CryptoType for Public {
|
||||
@@ -552,7 +558,7 @@ impl CryptoType for Pair {
|
||||
mod test {
|
||||
use super::*;
|
||||
use hex_literal::hex;
|
||||
use crate::crypto::{DEV_PHRASE, set_default_ss58_version};
|
||||
use crate::{crypto::{DEV_PHRASE, set_default_ss58_version}, keccak_256};
|
||||
use serde_json;
|
||||
use crate::crypto::PublicError;
|
||||
|
||||
@@ -761,4 +767,28 @@ mod test {
|
||||
// Poorly-sized
|
||||
assert!(deserialize_signature("\"abc123\"").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_prehashed_works() {
|
||||
let (pair, _, _) = Pair::generate_with_phrase(Some("password"));
|
||||
|
||||
// `msg` shouldn't be mangled
|
||||
let msg = [0u8; 32];
|
||||
let sig1 = pair.sign_prehashed(&msg);
|
||||
let sig2: Signature = secp256k1::sign(&secp256k1::Message::parse(&msg), &pair.secret).into();
|
||||
|
||||
assert_eq!(sig1, sig2);
|
||||
|
||||
// signature is actually different
|
||||
let sig2 = pair.sign(&msg);
|
||||
|
||||
assert_ne!(sig1, sig2);
|
||||
|
||||
// using pre-hashed `msg` works
|
||||
let msg = keccak_256(b"this should be hashed");
|
||||
let sig1 = pair.sign_prehashed(&msg);
|
||||
let sig2: Signature = secp256k1::sign(&secp256k1::Message::parse(&msg), &pair.secret).into();
|
||||
|
||||
assert_eq!(sig1, sig2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,6 +194,20 @@ pub trait CryptoStore: Send + Sync {
|
||||
public: &sr25519::Public,
|
||||
transcript_data: VRFTranscriptData,
|
||||
) -> Result<Option<VRFSignature>, Error>;
|
||||
|
||||
/// Sign pre-hashed
|
||||
///
|
||||
/// Signs a pre-hashed message with the private key that matches
|
||||
/// the ECDSA public key passed.
|
||||
///
|
||||
/// Returns the SCALE encoded signature if key is found and supported,
|
||||
/// `None` if the key doesn't exist or an error when something failed.
|
||||
async fn ecdsa_sign_prehashed(
|
||||
&self,
|
||||
id: KeyTypeId,
|
||||
public: &ecdsa::Public,
|
||||
msg: &[u8; 32],
|
||||
) -> Result<Option<ecdsa::Signature>, Error>;
|
||||
}
|
||||
|
||||
/// Sync version of the CryptoStore
|
||||
@@ -353,6 +367,20 @@ pub trait SyncCryptoStore: CryptoStore + Send + Sync {
|
||||
public: &sr25519::Public,
|
||||
transcript_data: VRFTranscriptData,
|
||||
) -> Result<Option<VRFSignature>, Error>;
|
||||
|
||||
/// Sign pre-hashed
|
||||
///
|
||||
/// Signs a pre-hashed message with the private key that matches
|
||||
/// the ECDSA public key passed.
|
||||
///
|
||||
/// Returns the SCALE encoded signature if key is found and supported,
|
||||
/// `None` if the key doesn't exist or an error when something failed.
|
||||
fn ecdsa_sign_prehashed(
|
||||
&self,
|
||||
id: KeyTypeId,
|
||||
public: &ecdsa::Public,
|
||||
msg: &[u8; 32],
|
||||
) -> Result<Option<ecdsa::Signature>, Error>;
|
||||
}
|
||||
|
||||
/// A pointer to a keystore.
|
||||
|
||||
@@ -22,6 +22,7 @@ use sp_core::{
|
||||
crypto::{Pair, Public, CryptoTypePublicPair},
|
||||
ed25519, sr25519, ecdsa,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
{CryptoStore, SyncCryptoStorePtr, Error, SyncCryptoStore},
|
||||
vrf::{VRFTranscriptData, VRFSignature, make_transcript},
|
||||
@@ -144,6 +145,15 @@ impl CryptoStore for KeyStore {
|
||||
) -> Result<Option<VRFSignature>, Error> {
|
||||
SyncCryptoStore::sr25519_vrf_sign(self, key_type, public, transcript_data)
|
||||
}
|
||||
|
||||
async fn ecdsa_sign_prehashed(
|
||||
&self,
|
||||
id: KeyTypeId,
|
||||
public: &ecdsa::Public,
|
||||
msg: &[u8; 32],
|
||||
) -> Result<Option<ecdsa::Signature>, Error> {
|
||||
SyncCryptoStore::ecdsa_sign_prehashed(self, id, public, msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl SyncCryptoStore for KeyStore {
|
||||
@@ -325,6 +335,16 @@ impl SyncCryptoStore for KeyStore {
|
||||
proof,
|
||||
}))
|
||||
}
|
||||
|
||||
fn ecdsa_sign_prehashed(
|
||||
&self,
|
||||
id: KeyTypeId,
|
||||
public: &ecdsa::Public,
|
||||
msg: &[u8; 32],
|
||||
) -> Result<Option<ecdsa::Signature>, Error> {
|
||||
let pair = self.ecdsa_key_pair(id, public);
|
||||
pair.map(|k| k.sign_prehashed(msg)).map(Ok).transpose()
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<SyncCryptoStorePtr> for KeyStore {
|
||||
@@ -342,7 +362,7 @@ impl Into<Arc<dyn CryptoStore>> for KeyStore {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_core::{sr25519, testing::{ED25519, SR25519}};
|
||||
use sp_core::{sr25519, testing::{ED25519, SR25519, ECDSA}};
|
||||
use crate::{SyncCryptoStore, vrf::VRFTranscriptValue};
|
||||
|
||||
#[test]
|
||||
@@ -416,4 +436,25 @@ mod tests {
|
||||
|
||||
assert!(result.unwrap().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ecdsa_sign_prehashed_works() {
|
||||
let store = KeyStore::new();
|
||||
|
||||
let suri = "//Alice";
|
||||
let pair = ecdsa::Pair::from_string(suri, None).unwrap();
|
||||
|
||||
let msg = sp_core::keccak_256(b"this should be a hashed message");
|
||||
|
||||
// no key in key store
|
||||
let res = SyncCryptoStore::ecdsa_sign_prehashed(&store, ECDSA, &pair.public(), &msg).unwrap();
|
||||
assert!(res.is_none());
|
||||
|
||||
// insert key, sign again
|
||||
let res = SyncCryptoStore::insert_unknown(&store, ECDSA, suri, pair.public().as_ref()).unwrap();
|
||||
assert_eq!((), res);
|
||||
|
||||
let res = SyncCryptoStore::ecdsa_sign_prehashed(&store, ECDSA, &pair.public(), &msg).unwrap();
|
||||
assert!(res.is_some());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user