Skip to content
This repository has been archived by the owner on Jun 3, 2020. It is now read-only.

Commit

Permalink
Merge pull request #181 from tendermint/zaki/tendermint_secp256k1
Browse files Browse the repository at this point in the history
Support for secp256k1 keys in tendermint-rs
  • Loading branch information
tarcieri committed Feb 24, 2019
2 parents 994b058 + 37fcd35 commit d005a26
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 34 deletions.
50 changes: 35 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ serde_derive = "1"
serde_json = "1"
sha2 = "0.8"
signal-hook = "0.1.7"
signatory = { version = "0.11", features = ["ed25519"] }
signatory = { version = "0.11.1", features = ["ed25519", "ecdsa"] }
signatory-dalek = "0.11"
signatory-secp256k1 = "0.11"
signatory-ledger-tm = { version = "0.11", optional = true }
subtle-encoding = "0.3"
tendermint = { version = "0.2", path = "tendermint-rs" }
Expand Down
2 changes: 1 addition & 1 deletion tendermint-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ rand_os = { version = "0.1", optional = true }
ring = { version = "0.14", optional = true }
serde = { version = "1", optional = true }
serde_derive = { version = "1", optional = true }
signatory = { version = "0.11", optional = true, features = ["ed25519"] }
signatory = { version = "0.11.1", optional = true, features = ["ed25519","ecdsa"] }
signatory-dalek = { version = "0.11", optional = true }
sha2 = { version = "0.8", optional = true, default-features = false }
subtle-encoding = { version = "0.3", features = ["bech32-preview"] }
Expand Down
120 changes: 103 additions & 17 deletions tendermint-rs/src/public_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,119 @@

use crate::error::Error;
use sha2::{Digest, Sha256};
use signatory::ed25519;
use signatory::{ecdsa::curve::secp256k1, ed25519};
use std::fmt::{self, Display};
use subtle_encoding::bech32;

/// Validator signing keys used for authenticating consensus protocol messages
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum ConsensusKey {
pub enum TendermintKey {
/// Ed25519 consensus keys
Ed25519(ed25519::PublicKey),
/// Secp256k1 consensus keys
Secp256k1(secp256k1::PublicKey),
}

impl ConsensusKey {
/// Validator signing keys used for authenticating consensus protocol messages
pub struct ConsensusKey(TendermintKey);
/// User signing keys used for interacting with accounts in the state machine
pub struct AccountKey(TendermintKey);

impl TendermintKey {
/// From raw secp256k1 public key bytes
pub fn from_raw_secp256k1(bytes: &[u8]) -> Result<TendermintKey, Error> {
Ok(TendermintKey::Secp256k1(secp256k1::PublicKey::from_bytes(
bytes,
)?))
}

/// From raw Ed25519 public key bytes
pub fn from_raw_ed25519(bytes: &[u8]) -> Result<ConsensusKey, Error> {
Ok(ConsensusKey::Ed25519(ed25519::PublicKey::from_bytes(
pub fn from_raw_ed25519(bytes: &[u8]) -> Result<TendermintKey, Error> {
Ok(TendermintKey::Ed25519(ed25519::PublicKey::from_bytes(
bytes,
)?))
}

/// Get Ed25519 public key
pub fn ed25519(self) -> Option<ed25519::PublicKey> {
match self {
ConsensusKey::Ed25519(pk) => Some(pk),
TendermintKey::Ed25519(pk) => Some(pk),
_ => None,
}
}
}

impl Display for ConsensusKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//Amino prefix for Pubkey
let mut key_bytes: Vec<u8> = vec![0x16, 0x24, 0xDE, 0x64, 0x20];
match self {
ConsensusKey::Ed25519(ref pk) => {
let key_bytes: Vec<u8> = match self.0 {
TendermintKey::Ed25519(ref pk) => {
//Amino prefix for Pubkey
let mut key_bytes = vec![0x16, 0x24, 0xDE, 0x64, 0x20];
key_bytes.extend(pk.as_bytes());
bech32::encode("cosmosvalconspub", &key_bytes).fmt(f)
key_bytes
}
}
TendermintKey::Secp256k1(ref pk) => {
let mut key_bytes = vec![0xEB, 0x5A, 0xE9, 0x87, 0x21];
key_bytes.extend(pk.as_bytes());
key_bytes
}
};
bech32::encode("cosmosvalconspub", &key_bytes).fmt(f)
}
}

impl Display for AccountKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let key_bytes: Vec<u8> = match self.0 {
TendermintKey::Ed25519(ref pk) => {
//Amino prefix for Pubkey
let mut key_bytes = vec![0x16, 0x24, 0xDE, 0x64, 0x20];
key_bytes.extend(pk.as_bytes());
key_bytes
}
TendermintKey::Secp256k1(ref pk) => {
let mut key_bytes = vec![0xEB, 0x5A, 0xE9, 0x87, 0x21];
key_bytes.extend(pk.as_bytes());
key_bytes
}
};
bech32::encode("cosmospub", &key_bytes).fmt(f)
}
}

impl From<ed25519::PublicKey> for TendermintKey {
fn from(pk: ed25519::PublicKey) -> TendermintKey {
TendermintKey::Ed25519(pk)
}
}

impl From<secp256k1::PublicKey> for TendermintKey {
fn from(pk: secp256k1::PublicKey) -> TendermintKey {
TendermintKey::Secp256k1(pk)
}
}

impl From<ed25519::PublicKey> for ConsensusKey {
fn from(pk: ed25519::PublicKey) -> ConsensusKey {
ConsensusKey::Ed25519(pk)
ConsensusKey(TendermintKey::Ed25519(pk))
}
}

impl From<secp256k1::PublicKey> for ConsensusKey {
fn from(pk: secp256k1::PublicKey) -> ConsensusKey {
ConsensusKey(TendermintKey::Secp256k1(pk))
}
}

impl From<ed25519::PublicKey> for AccountKey {
fn from(pk: ed25519::PublicKey) -> AccountKey {
AccountKey(TendermintKey::Ed25519(pk))
}
}

impl From<secp256k1::PublicKey> for AccountKey {
fn from(pk: secp256k1::PublicKey) -> AccountKey {
AccountKey(TendermintKey::Secp256k1(pk))
}
}

Expand Down Expand Up @@ -93,7 +163,7 @@ impl From<ed25519::PublicKey> for SecretConnectionKey {

#[cfg(test)]
mod tests {
use super::{ConsensusKey, SecretConnectionKey};
use super::{AccountKey, ConsensusKey, SecretConnectionKey, TendermintKey};
use subtle_encoding::hex;

const EXAMPLE_SECRET_CONN_KEY: &str =
Expand All @@ -117,13 +187,29 @@ mod tests {

#[test]
fn test_consensus_serialization() {
let example_key =
ConsensusKey::from_raw_ed25519(&hex::decode_upper(EXAMPLE_CONSENSUS_KEY).unwrap())
.unwrap();
let example_key = ConsensusKey(
TendermintKey::from_raw_ed25519(&hex::decode_upper(EXAMPLE_CONSENSUS_KEY).unwrap())
.unwrap(),
);

assert_eq!(
example_key.to_string(),
"cosmosvalconspub1zcjduepqfgjuveq2raetnjt4xwpffm63kmguxv2chdhvhf5lhslmtgeunh8qmf7exk"
);
}

const EXAMPLE_ACCOUNT_KEY: &str =
"02A1633CAFCC01EBFB6D78E39F687A1F0995C62FC95F51EAD10A02EE0BE551B5DC";
#[test]
fn test_account_serialization() {
let example_key = AccountKey(
TendermintKey::from_raw_secp256k1(&hex::decode_upper(EXAMPLE_ACCOUNT_KEY).unwrap())
.unwrap(),
);

assert_eq!(
example_key.to_string(),
"cosmospub1addwnpepq2skx090esq7h7md0r3e76r6ruyet330e904r6k3pgpwuzl92x6actrt4uq"
);
}
}

0 comments on commit d005a26

Please sign in to comment.