Skip to content

Commit d92bbaa

Browse files
committed
runtime-sdk: Add in-memory signers for Ed25519 and Sr25519
1 parent 3fd2112 commit d92bbaa

2 files changed

Lines changed: 91 additions & 13 deletions

File tree

runtime-sdk/src/crypto/signature/sr25519.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,68 @@ impl From<&'static str> for PublicKey {
6969
PublicKey::from_bytes(&base64::decode(s).unwrap()).unwrap()
7070
}
7171
}
72+
73+
/// A memory-backed signer for Sr25519.
74+
pub struct MemorySigner {
75+
kp: schnorrkel::Keypair,
76+
}
77+
78+
impl MemorySigner {
79+
/// Creates a new signer from a seed.
80+
pub fn new_from_seed(seed: &[u8]) -> Result<Self, Error> {
81+
let sk =
82+
schnorrkel::MiniSecretKey::from_bytes(&seed).map_err(|_| Error::InvalidArgument)?;
83+
let kp = sk.expand_to_keypair(schnorrkel::keys::ExpansionMode::Ed25519);
84+
Ok(Self { kp })
85+
}
86+
87+
/// Generates a new signer deterministically from a test key name string.
88+
pub fn new_test(name: &str) -> Self {
89+
let mut digest = Sha512Trunc256::new();
90+
digest.update(name.as_bytes());
91+
let seed = digest.finalize();
92+
93+
Self::new_from_seed(&seed).unwrap()
94+
}
95+
96+
/// Public key corresponding to the signer.
97+
pub fn public(&self) -> PublicKey {
98+
PublicKey::from_bytes(&self.kp.public.to_bytes()).unwrap()
99+
}
100+
101+
/// Generates a signature with the private key over the context and message.
102+
pub fn context_sign(&self, context: &[u8], message: &[u8]) -> Result<Signature, Error> {
103+
// Convert the context to a Sr25519 SigningContext.
104+
let context = schnorrkel::context::SigningContext::new(context);
105+
106+
// Generate a SigningTranscript from the context, and a pre-hash
107+
// of the message.
108+
//
109+
// Note: This requires using Sha512Trunc256 instead of our hash,
110+
// due to the need for FixedOutput.
111+
let mut digest = Sha512Trunc256::new();
112+
digest.update(message);
113+
let transcript = context.hash256(digest);
114+
115+
let signature = self.kp.sign(transcript);
116+
117+
Ok(signature.to_bytes().to_vec().into())
118+
}
119+
}
120+
121+
#[cfg(test)]
122+
mod test {
123+
use super::*;
124+
125+
#[test]
126+
fn test_memory_signer() {
127+
let signer = MemorySigner::new_test("memory signer test");
128+
let ctx = b"oasis-core/test: context";
129+
let message = b"this is a message";
130+
let signature = signer.context_sign(ctx, message).unwrap();
131+
let pk = signer.public();
132+
133+
pk.verify(ctx, message, &signature)
134+
.expect("signature should verify");
135+
}
136+
}

runtime-sdk/src/testing/keys.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
//! Module that contains known test keys.
22
3-
// TODO: Should be derived from seeds once implemented in the Rust version.
4-
53
/// Define an ed25519 test key.
64
macro_rules! test_key_ed25519 {
7-
($doc:expr, $name:ident, $pk:expr) => {
5+
($doc:expr, $name:ident, $seed:expr) => {
86
#[doc = " Test key "]
97
#[doc=$doc]
108
#[doc = "."]
@@ -25,7 +23,14 @@ macro_rules! test_key_ed25519 {
2523
#[doc=$doc]
2624
#[doc = "."]
2725
pub fn pk_ed25519() -> ed25519::PublicKey {
28-
$pk.into()
26+
signer().public()
27+
}
28+
29+
#[doc = " Test Ed25519 signer "]
30+
#[doc=$doc]
31+
#[doc = "."]
32+
pub fn signer() -> ed25519::MemorySigner {
33+
ed25519::MemorySigner::new_test($seed)
2934
}
3035

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

9196
/// Define an sr25519 test key.
9297
macro_rules! test_key_sr25519 {
93-
($doc:expr, $name:ident, $pk:expr) => {
98+
($doc:expr, $name:ident, $seed:expr) => {
9499
#[doc = " Test key "]
95100
#[doc=$doc]
96101
#[doc = "."]
@@ -111,7 +116,14 @@ macro_rules! test_key_sr25519 {
111116
#[doc=$doc]
112117
#[doc = "."]
113118
pub fn pk_sr25519() -> sr25519::PublicKey {
114-
$pk.into()
119+
signer().public()
120+
}
121+
122+
#[doc = " Test Sr25519 signer "]
123+
#[doc=$doc]
124+
#[doc = "."]
125+
pub fn signer() -> sr25519::MemorySigner {
126+
sr25519::MemorySigner::new_test($seed)
115127
}
116128

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

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

0 commit comments

Comments
 (0)