Key generation utility (#176)

* RPCs for versioning.

* Build fix for bad merge.

* Add system_name RPC

* Fix tests.

* Fix demo build.

* Remove BadFormat.

* Add ss58check encoding and subkey.

* Improvements.

* Update Cargo.toml
This commit is contained in:
Gav Wood
2018-05-29 18:05:50 +02:00
committed by GitHub
parent 757e5beb8d
commit c831e7c511
6 changed files with 137 additions and 0 deletions
+2
View File
@@ -8,3 +8,5 @@ ring = "0.12"
untrusted = "0.5"
substrate-primitives = { version = "0.1", path = "../primitives" }
hex-literal = "0.1"
base58 = "0.1"
blake2-rfc = "0.2"
+55
View File
@@ -17,11 +17,14 @@
//! Simple Ed25519 API.
extern crate ring;
extern crate base58;
extern crate substrate_primitives as primitives;
extern crate untrusted;
extern crate blake2_rfc;
use ring::{rand, signature};
use primitives::hash::H512;
use base58::{ToBase58, FromBase58};
#[cfg(test)]
#[macro_use]
@@ -67,6 +70,14 @@ impl ::std::hash::Hash for Public {
}
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum PublicError {
BadBase58,
BadLength,
UnknownVersion,
InvalidChecksum,
}
impl Public {
/// A new instance from the given 32-byte `data`.
pub fn from_raw(data: [u8; 32]) -> Self {
@@ -80,6 +91,24 @@ impl Public {
Public(r)
}
/// Some if the string is a properly encoded SS58Check address.
pub fn from_ss58check(s: &str) -> Result<Self, PublicError> {
let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding.
if d.len() != 35 {
// Invalid length.
return Err(PublicError::BadLength);
}
if d[0] != 42 {
// Invalid version.
return Err(PublicError::UnknownVersion);
}
if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] {
// Invalid checksum.
return Err(PublicError::InvalidChecksum);
}
Ok(Self::from_slice(&d[1..33]))
}
/// Return a `Vec<u8>` filled with raw data.
pub fn to_raw_vec(self) -> Vec<u8> {
let r: &[u8; 32] = self.as_ref();
@@ -96,6 +125,15 @@ impl Public {
pub fn as_array_ref(&self) -> &[u8; 32] {
self.as_ref()
}
/// Return the ss58-check string for this key.
pub fn to_ss58check(&self) -> String {
let mut v = vec![42u8];
v.extend(self.as_slice());
let r = blake2_rfc::blake2b::blake2b(64, &[], &v);
v.extend(&r.as_bytes()[0..2]);
v.to_base58()
}
}
impl AsRef<[u8; 32]> for Public {
@@ -281,4 +319,21 @@ mod test {
let pair = Pair::generate();
let _pair2 = pair.derive_child_probably_bad(b"session_1234");
}
#[test]
fn ss58check_roundtrip_works() {
let pair = Pair::from_seed(b"12345678901234567890123456789012");
let public = pair.public();
let s = public.to_ss58check();
println!("Correct: {}", s);
let cmp = Public::from_ss58check(&s).unwrap();
assert_eq!(cmp, public);
}
#[test]
fn ss58check_known_works() {
let k = "5CGavy93sZgPPjHyziRohwVumxiHXMGmQLyuqQP4ZFx5vRU9";
let enc = hex!["090fa15cb5b1666222fff584b4cc2b1761fe1e238346b340491b37e25ea183ff"];
assert_eq!(Public::from_ss58check(k).unwrap(), Public::from_raw(enc));
}
}