Skip to content

Commit

Permalink
runtime-sdk: Add in-memory signers for Ed25519 and Sr25519
Browse files Browse the repository at this point in the history
  • Loading branch information
kostko committed Jan 25, 2024
1 parent 3fd2112 commit d92bbaa
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 13 deletions.
65 changes: 65 additions & 0 deletions runtime-sdk/src/crypto/signature/sr25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,68 @@ impl From<&'static str> for PublicKey {
PublicKey::from_bytes(&base64::decode(s).unwrap()).unwrap()
}
}

/// A memory-backed signer for Sr25519.
pub struct MemorySigner {
kp: schnorrkel::Keypair,
}

impl MemorySigner {
/// Creates a new signer from a seed.
pub fn new_from_seed(seed: &[u8]) -> Result<Self, Error> {
let sk =
schnorrkel::MiniSecretKey::from_bytes(&seed).map_err(|_| Error::InvalidArgument)?;
let kp = sk.expand_to_keypair(schnorrkel::keys::ExpansionMode::Ed25519);
Ok(Self { kp })
}

/// Generates a new signer deterministically from a test key name string.
pub fn new_test(name: &str) -> Self {
let mut digest = Sha512Trunc256::new();
digest.update(name.as_bytes());
let seed = digest.finalize();

Self::new_from_seed(&seed).unwrap()
}

/// Public key corresponding to the signer.
pub fn public(&self) -> PublicKey {
PublicKey::from_bytes(&self.kp.public.to_bytes()).unwrap()
}

/// Generates a signature with the private key over the context and message.
pub fn context_sign(&self, context: &[u8], message: &[u8]) -> Result<Signature, Error> {
// Convert the context to a Sr25519 SigningContext.
let context = schnorrkel::context::SigningContext::new(context);

// Generate a SigningTranscript from the context, and a pre-hash
// of the message.
//
// Note: This requires using Sha512Trunc256 instead of our hash,
// due to the need for FixedOutput.
let mut digest = Sha512Trunc256::new();
digest.update(message);
let transcript = context.hash256(digest);

let signature = self.kp.sign(transcript);

Ok(signature.to_bytes().to_vec().into())
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_memory_signer() {
let signer = MemorySigner::new_test("memory signer test");
let ctx = b"oasis-core/test: context";
let message = b"this is a message";
let signature = signer.context_sign(ctx, message).unwrap();
let pk = signer.public();

pk.verify(ctx, message, &signature)
.expect("signature should verify");
}
}
39 changes: 26 additions & 13 deletions runtime-sdk/src/testing/keys.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
//! Module that contains known test keys.
// TODO: Should be derived from seeds once implemented in the Rust version.

/// Define an ed25519 test key.
macro_rules! test_key_ed25519 {
($doc:expr, $name:ident, $pk:expr) => {
($doc:expr, $name:ident, $seed:expr) => {
#[doc = " Test key "]
#[doc=$doc]
#[doc = "."]
Expand All @@ -25,7 +23,14 @@ macro_rules! test_key_ed25519 {
#[doc=$doc]
#[doc = "."]
pub fn pk_ed25519() -> ed25519::PublicKey {
$pk.into()
signer().public()
}

#[doc = " Test Ed25519 signer "]
#[doc=$doc]
#[doc = "."]
pub fn signer() -> ed25519::MemorySigner {
ed25519::MemorySigner::new_test($seed)
}

#[doc = " Test address derivation information "]
Expand Down Expand Up @@ -90,7 +95,7 @@ macro_rules! test_key_secp256k1 {

/// Define an sr25519 test key.
macro_rules! test_key_sr25519 {
($doc:expr, $name:ident, $pk:expr) => {
($doc:expr, $name:ident, $seed:expr) => {
#[doc = " Test key "]
#[doc=$doc]
#[doc = "."]
Expand All @@ -111,7 +116,14 @@ macro_rules! test_key_sr25519 {
#[doc=$doc]
#[doc = "."]
pub fn pk_sr25519() -> sr25519::PublicKey {
$pk.into()
signer().public()
}

#[doc = " Test Sr25519 signer "]
#[doc=$doc]
#[doc = "."]
pub fn signer() -> sr25519::MemorySigner {
sr25519::MemorySigner::new_test($seed)
}

#[doc = " Test address derivation information "]
Expand All @@ -131,10 +143,11 @@ macro_rules! test_key_sr25519 {
};
}

test_key_ed25519!("A", alice, "NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=");
test_key_ed25519!("B", bob, "YgkEiVSR4SMQdfXw+ppuFYlqH0seutnCKk8KG8PyAx0=");
test_key_ed25519!("C", charlie, "8l1AQE+ETOPLckiNJ7NOD+AfZdaPw6wguir/vSF11YI=");
test_key_secp256k1!("D", dave, "AwF6GNjbybMzhi3XRj5R1oTiMMkO1nAwB7NZAlH1X4BE");
test_key_secp256k1!("E", erin, "A9i0oSK+5sLSONbMYGmaFUA+Fb8zzqYEMUMspacIgO09");
test_key_sr25519!("F", frank, "ljm9ZwdAldhlyWM2B4C+3gQZis+ceaxnt6QA4rOcP0k=");
test_key_sr25519!("G", grace, "0MHrNhjVTOFWmsOgpWcC3L8jIX3ZatKr0/yxMPtwckc=");
test_key_ed25519!("Alice", alice, "oasis-runtime-sdk/test-keys: alice");
test_key_ed25519!("Bob", bob, "oasis-runtime-sdk/test-keys: bob");
test_key_ed25519!("Charlie", charlie, "oasis-runtime-sdk/test-keys: charlie");
test_key_ed25519!("Cory", cory, "ekiden test entity key seed");
test_key_secp256k1!("Dave", dave, "AwF6GNjbybMzhi3XRj5R1oTiMMkO1nAwB7NZAlH1X4BE");
test_key_secp256k1!("Erin", erin, "A9i0oSK+5sLSONbMYGmaFUA+Fb8zzqYEMUMspacIgO09");
test_key_sr25519!("Frank", frank, "oasis-runtime-sdk/test-keys: frank");
test_key_sr25519!("Grace", grace, "oasis-runtime-sdk/test-keys: grace");

0 comments on commit d92bbaa

Please sign in to comment.