Merge pull request #7336 from paritytech/secretstore_rpc_sign_raw_hash
SecretStore: secretstore_signRawHash method
This commit is contained in:
commit
483480d7a1
@ -454,7 +454,7 @@ usage! {
|
|||||||
"--jsonrpc-interface=[IP]",
|
"--jsonrpc-interface=[IP]",
|
||||||
"Specify the hostname portion of the JSONRPC API server, IP should be an interface's IP address, or all (all interfaces) or local.",
|
"Specify the hostname portion of the JSONRPC API server, IP should be an interface's IP address, or all (all interfaces) or local.",
|
||||||
|
|
||||||
ARG arg_jsonrpc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc,secretstore,shh,shh_pubsub", or |c: &Config| otry!(c.rpc).apis.as_ref().map(|vec| vec.join(",")),
|
ARG arg_jsonrpc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc,shh,shh_pubsub", or |c: &Config| otry!(c.rpc).apis.as_ref().map(|vec| vec.join(",")),
|
||||||
"--jsonrpc-apis=[APIS]",
|
"--jsonrpc-apis=[APIS]",
|
||||||
"Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API name. Possible name are all, safe, web3, eth, net, personal, parity, parity_set, traces, rpc, parity_accounts. You can also disable a specific API by putting '-' in the front: all,-personal.",
|
"Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API name. Possible name are all, safe, web3, eth, net, personal, parity, parity_set, traces, rpc, parity_accounts. You can also disable a specific API by putting '-' in the front: all,-personal.",
|
||||||
|
|
||||||
@ -487,7 +487,7 @@ usage! {
|
|||||||
"--ws-interface=[IP]",
|
"--ws-interface=[IP]",
|
||||||
"Specify the hostname portion of the WebSockets server, IP should be an interface's IP address, or all (all interfaces) or local.",
|
"Specify the hostname portion of the WebSockets server, IP should be an interface's IP address, or all (all interfaces) or local.",
|
||||||
|
|
||||||
ARG arg_ws_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc,secretstore,shh,shh_pubsub", or |c: &Config| otry!(c.websockets).apis.as_ref().map(|vec| vec.join(",")),
|
ARG arg_ws_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc,shh,shh_pubsub", or |c: &Config| otry!(c.websockets).apis.as_ref().map(|vec| vec.join(",")),
|
||||||
"--ws-apis=[APIS]",
|
"--ws-apis=[APIS]",
|
||||||
"Specify the APIs available through the WebSockets interface. APIS is a comma-delimited list of API name. Possible name are web3, eth, pubsub, net, personal, parity, parity_set, traces, rpc, parity_accounts..",
|
"Specify the APIs available through the WebSockets interface. APIS is a comma-delimited list of API name. Possible name are web3, eth, pubsub, net, personal, parity, parity_set, traces, rpc, parity_accounts..",
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ usage! {
|
|||||||
"--ipc-path=[PATH]",
|
"--ipc-path=[PATH]",
|
||||||
"Specify custom path for JSON-RPC over IPC service.",
|
"Specify custom path for JSON-RPC over IPC service.",
|
||||||
|
|
||||||
ARG arg_ipc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,traces,rpc,secretstore,shh,shh_pubsub", or |c: &Config| otry!(c.ipc).apis.as_ref().map(|vec| vec.join(",")),
|
ARG arg_ipc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,traces,rpc,shh,shh_pubsub", or |c: &Config| otry!(c.ipc).apis.as_ref().map(|vec| vec.join(",")),
|
||||||
"--ipc-apis=[APIS]",
|
"--ipc-apis=[APIS]",
|
||||||
"Specify custom API set available via JSON-RPC over IPC.",
|
"Specify custom API set available via JSON-RPC over IPC.",
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ pub enum Api {
|
|||||||
Traces,
|
Traces,
|
||||||
/// Rpc (Safe)
|
/// Rpc (Safe)
|
||||||
Rpc,
|
Rpc,
|
||||||
/// SecretStore (Safe)
|
/// SecretStore (UNSAFE: arbitrary hash signing)
|
||||||
SecretStore,
|
SecretStore,
|
||||||
/// Whisper (Safe)
|
/// Whisper (Safe)
|
||||||
// TODO: _if_ someone guesses someone else's key or filter IDs they can remove
|
// TODO: _if_ someone guesses someone else's key or filter IDs they can remove
|
||||||
@ -602,7 +602,6 @@ impl ApiSet {
|
|||||||
Api::EthPubSub,
|
Api::EthPubSub,
|
||||||
Api::Parity,
|
Api::Parity,
|
||||||
Api::Rpc,
|
Api::Rpc,
|
||||||
Api::SecretStore,
|
|
||||||
Api::Whisper,
|
Api::Whisper,
|
||||||
Api::WhisperPubSub,
|
Api::WhisperPubSub,
|
||||||
].into_iter().cloned().collect();
|
].into_iter().cloned().collect();
|
||||||
@ -627,6 +626,7 @@ impl ApiSet {
|
|||||||
public_list.insert(Api::ParityAccounts);
|
public_list.insert(Api::ParityAccounts);
|
||||||
public_list.insert(Api::ParitySet);
|
public_list.insert(Api::ParitySet);
|
||||||
public_list.insert(Api::Signer);
|
public_list.insert(Api::Signer);
|
||||||
|
public_list.insert(Api::SecretStore);
|
||||||
public_list
|
public_list
|
||||||
},
|
},
|
||||||
ApiSet::All => {
|
ApiSet::All => {
|
||||||
@ -636,6 +636,7 @@ impl ApiSet {
|
|||||||
public_list.insert(Api::ParitySet);
|
public_list.insert(Api::ParitySet);
|
||||||
public_list.insert(Api::Signer);
|
public_list.insert(Api::Signer);
|
||||||
public_list.insert(Api::Personal);
|
public_list.insert(Api::Personal);
|
||||||
|
public_list.insert(Api::SecretStore);
|
||||||
public_list
|
public_list
|
||||||
},
|
},
|
||||||
ApiSet::PubSub => [
|
ApiSet::PubSub => [
|
||||||
@ -686,7 +687,7 @@ mod test {
|
|||||||
fn test_api_set_unsafe_context() {
|
fn test_api_set_unsafe_context() {
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
// make sure this list contains only SAFE methods
|
// make sure this list contains only SAFE methods
|
||||||
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::ParityPubSub, Api::Traces, Api::Rpc, Api::SecretStore, Api::Whisper, Api::WhisperPubSub,
|
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::ParityPubSub, Api::Traces, Api::Rpc, Api::Whisper, Api::WhisperPubSub,
|
||||||
].into_iter().collect();
|
].into_iter().collect();
|
||||||
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
|
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
|
||||||
}
|
}
|
||||||
@ -695,7 +696,7 @@ mod test {
|
|||||||
fn test_api_set_ipc_context() {
|
fn test_api_set_ipc_context() {
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
// safe
|
// safe
|
||||||
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::ParityPubSub, Api::Traces, Api::Rpc, Api::SecretStore, Api::Whisper, Api::WhisperPubSub,
|
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::ParityPubSub, Api::Traces, Api::Rpc, Api::Whisper, Api::WhisperPubSub,
|
||||||
// semi-safe
|
// semi-safe
|
||||||
Api::ParityAccounts
|
Api::ParityAccounts
|
||||||
].into_iter().collect();
|
].into_iter().collect();
|
||||||
@ -737,7 +738,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_safe_parsing() {
|
fn test_safe_parsing() {
|
||||||
assert_eq!("safe".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
|
assert_eq!("safe".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
|
||||||
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::ParityPubSub, Api::Traces, Api::Rpc, Api::SecretStore, Api::Whisper, Api::WhisperPubSub,
|
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::ParityPubSub, Api::Traces, Api::Rpc, Api::Whisper, Api::WhisperPubSub,
|
||||||
].into_iter().collect()));
|
].into_iter().collect()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ use v1::helpers::errors;
|
|||||||
use v1::helpers::accounts::unwrap_provider;
|
use v1::helpers::accounts::unwrap_provider;
|
||||||
use v1::helpers::secretstore::{encrypt_document, decrypt_document, decrypt_document_with_shadow, ordered_servers_keccak};
|
use v1::helpers::secretstore::{encrypt_document, decrypt_document, decrypt_document_with_shadow, ordered_servers_keccak};
|
||||||
use v1::traits::SecretStore;
|
use v1::traits::SecretStore;
|
||||||
use v1::types::{H160, H512, Bytes};
|
use v1::types::{H160, H256, H512, Bytes};
|
||||||
|
|
||||||
/// Parity implementation.
|
/// Parity implementation.
|
||||||
pub struct SecretStoreClient {
|
pub struct SecretStoreClient {
|
||||||
@ -84,12 +84,15 @@ impl SecretStore for SecretStoreClient {
|
|||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_servers_set(&self, address: H160, password: String, servers_set: BTreeSet<H512>) -> Result<Bytes> {
|
fn servers_set_hash(&self, servers_set: BTreeSet<H512>) -> Result<H256> {
|
||||||
let servers_set_keccak_value = ordered_servers_keccak(servers_set);
|
Ok(ordered_servers_keccak(servers_set))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sign_raw_hash(&self, address: H160, password: String, raw_hash: H256) -> Result<Bytes> {
|
||||||
let store = self.account_provider()?;
|
let store = self.account_provider()?;
|
||||||
store
|
store
|
||||||
.sign(address.into(), Some(password), servers_set_keccak_value.into())
|
.sign(address.into(), Some(password), raw_hash.into())
|
||||||
.map(|s| Bytes::new((*s).to_vec()))
|
.map(|s| Bytes::new((*s).to_vec()))
|
||||||
.map_err(|e| errors::account("Could not sign servers set.", e))
|
.map_err(|e| errors::account("Could not sign raw hash.", e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ use v1::metadata::Metadata;
|
|||||||
use v1::SecretStoreClient;
|
use v1::SecretStoreClient;
|
||||||
use v1::traits::secretstore::SecretStore;
|
use v1::traits::secretstore::SecretStore;
|
||||||
use v1::helpers::secretstore::ordered_servers_keccak;
|
use v1::helpers::secretstore::ordered_servers_keccak;
|
||||||
|
use v1::types::H256;
|
||||||
|
|
||||||
struct Dependencies {
|
struct Dependencies {
|
||||||
pub accounts: Arc<AccountProvider>,
|
pub accounts: Arc<AccountProvider>,
|
||||||
@ -100,7 +101,29 @@ fn rpc_secretstore_shadow_decrypt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_secretstore_sign_servers_set() {
|
fn rpc_secretstore_servers_set_hash() {
|
||||||
|
let deps = Dependencies::new();
|
||||||
|
let io = deps.default_client();
|
||||||
|
|
||||||
|
// execute hashing request
|
||||||
|
let hashing_request = r#"{"jsonrpc": "2.0", "method": "secretstore_serversSetHash", "params":[
|
||||||
|
["0x843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91",
|
||||||
|
"0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]
|
||||||
|
], "id": 1}"#;
|
||||||
|
let hashing_response = io.handle_request_sync(&hashing_request).unwrap();
|
||||||
|
let hashing_response = hashing_response.replace(r#"{"jsonrpc":"2.0","result":"0x"#, "");
|
||||||
|
let hashing_response = hashing_response.replace(r#"","id":1}"#, "");
|
||||||
|
let hash: H256 = hashing_response.parse().unwrap();
|
||||||
|
|
||||||
|
let servers_set_keccak = ordered_servers_keccak(vec![
|
||||||
|
"843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91".parse().unwrap(),
|
||||||
|
"07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3".parse().unwrap()
|
||||||
|
].into_iter().collect());
|
||||||
|
assert_eq!(hash, servers_set_keccak);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rpc_secretstore_sign_raw_hash() {
|
||||||
let deps = Dependencies::new();
|
let deps = Dependencies::new();
|
||||||
let io = deps.default_client();
|
let io = deps.default_client();
|
||||||
|
|
||||||
@ -110,19 +133,14 @@ fn rpc_secretstore_sign_servers_set() {
|
|||||||
deps.accounts.insert_account(key_pair.secret().clone(), "password").unwrap();
|
deps.accounts.insert_account(key_pair.secret().clone(), "password").unwrap();
|
||||||
|
|
||||||
// execute signing request
|
// execute signing request
|
||||||
let signing_request = r#"{"jsonrpc": "2.0", "method": "secretstore_signServersSet", "params":[
|
let signing_request = r#"{"jsonrpc": "2.0", "method": "secretstore_signRawHash", "params":[
|
||||||
"0x00dfE63B22312ab4329aD0d28CaD8Af987A01932", "password",
|
"0x00dfE63B22312ab4329aD0d28CaD8Af987A01932", "password", "0x0000000000000000000000000000000000000000000000000000000000000001"
|
||||||
["0x843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91",
|
|
||||||
"0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]
|
|
||||||
], "id": 1}"#;
|
], "id": 1}"#;
|
||||||
let signing_response = io.handle_request_sync(&signing_request).unwrap();
|
let signing_response = io.handle_request_sync(&signing_request).unwrap();
|
||||||
let signing_response = signing_response.replace(r#"{"jsonrpc":"2.0","result":"0x"#, "");
|
let signing_response = signing_response.replace(r#"{"jsonrpc":"2.0","result":"0x"#, "");
|
||||||
let signing_response = signing_response.replace(r#"","id":1}"#, "");
|
let signing_response = signing_response.replace(r#"","id":1}"#, "");
|
||||||
let signature: Signature = signing_response.parse().unwrap();
|
let signature: Signature = signing_response.parse().unwrap();
|
||||||
|
|
||||||
let servers_set_keccak = ordered_servers_keccak(vec![
|
let hash = "0000000000000000000000000000000000000000000000000000000000000001".parse().unwrap();
|
||||||
"843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91".parse().unwrap(),
|
assert!(verify_public(key_pair.public(), &signature, &hash).unwrap());
|
||||||
"07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3".parse().unwrap()
|
|
||||||
].into_iter().collect());
|
|
||||||
assert!(verify_public(key_pair.public(), &signature, &servers_set_keccak.into()).unwrap());
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use jsonrpc_core::Result;
|
use jsonrpc_core::Result;
|
||||||
|
|
||||||
use v1::types::{H160, H512, Bytes};
|
use v1::types::{H160, H256, H512, Bytes};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Parity-specific rpc interface.
|
/// Parity-specific rpc interface.
|
||||||
@ -39,9 +39,16 @@ build_rpc_trait! {
|
|||||||
#[rpc(name = "secretstore_shadowDecrypt")]
|
#[rpc(name = "secretstore_shadowDecrypt")]
|
||||||
fn shadow_decrypt(&self, H160, String, H512, H512, Vec<Bytes>, Bytes) -> Result<Bytes>;
|
fn shadow_decrypt(&self, H160, String, H512, H512, Vec<Bytes>, Bytes) -> Result<Bytes>;
|
||||||
|
|
||||||
/// Sign servers set for use in ServersSetChange session.
|
/// Calculates the hash (keccak256) of servers set for using in ServersSetChange session.
|
||||||
/// Arguments: `account`, `password`, `servers_set`.
|
/// Returned hash must be signed later by using `secretstore_signRawHash` method.
|
||||||
#[rpc(name = "secretstore_signServersSet")]
|
/// Arguments: `servers_set`.
|
||||||
fn sign_servers_set(&self, H160, String, BTreeSet<H512>) -> Result<Bytes>;
|
#[rpc(name = "secretstore_serversSetHash")]
|
||||||
|
fn servers_set_hash(&self, BTreeSet<H512>) -> Result<H256>;
|
||||||
|
|
||||||
|
/// Generate recoverable ECDSA signature of raw hash.
|
||||||
|
/// Passed hash is treated as an input to the `sign` function (no prefixes added, no hash function is applied).
|
||||||
|
/// Arguments: `account`, `password`, `raw_hash`.
|
||||||
|
#[rpc(name = "secretstore_signRawHash")]
|
||||||
|
fn sign_raw_hash(&self, H160, String, H256) -> Result<Bytes>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user