Skip to content

Commit

Permalink
separate signing keys for each sbt issuer
Browse files Browse the repository at this point in the history
  • Loading branch information
Kirill-K-1 committed Aug 1, 2024
1 parent 1c53b13 commit 690f73b
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 51 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ Default configuration could be found in `./config/default.json` file.

- `listenAddress`: host:port to run the verifier service at. Defaults to `localhost:10000`
- `signer`: signer configuration
- `signingKey`: hex encoded private key to sign Human SBT requests to be used as arguments for Human SBT issuer smart contract call `sbtMint`. Should be set before app start
- `requestLifetime`: lifetime duration in millis for which the signed request will be valid to use for Human SBT issuer smart contract call `sbtMint`. Defaults to 60 seconds
- `keys`:
- `issuerHumanSBT`: hex encoded private key to sign Human SBT requests to be used as arguments for Human SBT issuer smart contract call `sbtMint`. Should be set before app start
- `issuerOGSBT`: hex encoded private key to sign Human SBT requests to be used as arguments for OG SBT issuer smart contract call `sbtMint`. Should be set before app start
- `issuerSNOSBT`: hex encoded private key to sign Human SBT requests to be used as arguments for SNO SBT issuer smart contract call `sbtMint`. Should be set before app start
- `requestLifetime`: lifetime duration in millis for which the signed request will be valid to use for SBT issuer smart contract call `sbtMint`. Defaults to 60 seconds
- `sbtLifetime`: lifetime duration in millis for Human SBT since minted for a user. Defaults to 100 years
- `fractal`: Fractal Id configuration
- `requestTokenUrl`: url used to exchange auth code for auth token. Could be found in Fractal Id documentation. Defaults to production env
Expand Down
6 changes: 5 additions & 1 deletion config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
"listenAddress": "0.0.0.0:10000",
"usersManagerSecret": null,
"signer": {
"signingKey": null,
"keys": {
"issuerHumanSBT": null,
"issuerOGSBT": null,
"issuerSNOSBT": null
},
"requestLifetime": 60000,
"sbtLifetime": 3153600000000,
"ogEligibleBefore": 1577836800
Expand Down
37 changes: 32 additions & 5 deletions user-verifier/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod signer;
mod validators_manager;
mod verification;

use shared::logger;
use shared::{logger, utils::get_eth_address};

use crate::config::AppConfig;

Expand All @@ -24,15 +24,42 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = shared::utils::load_config::<AppConfig>("./").await?;

tracing::info!(
"Signer's public address: 0x{}",
hex::encode(
"HumanSBT Signer's public address: 0x{}",
hex::encode(get_eth_address(
config
.signer
.signing_key
.keys
.issuer_human_sbt
.verifying_key()
.to_encoded_point(false)
.as_bytes()
)
))
);

tracing::info!(
"OGSBT Signer's public address: 0x{}",
hex::encode(get_eth_address(
config
.signer
.keys
.issuer_og_sbt
.verifying_key()
.to_encoded_point(false)
.as_bytes()
))
);

tracing::info!(
"SNOSBT Signer's public address: 0x{}",
hex::encode(get_eth_address(
config
.signer
.keys
.issuer_sno_sbt
.verifying_key()
.to_encoded_point(false)
.as_bytes()
))
);

server::start(config).await?;
Expand Down
85 changes: 69 additions & 16 deletions user-verifier/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ use crate::error::AppError;
#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SignerConfig {
#[serde(deserialize_with = "utils::de_secp256k1_signing_key")]
pub signing_key: SigningKey,
pub keys: SignerKeys,
#[serde(deserialize_with = "utils::de_secs_duration")]
pub request_lifetime: Duration,
#[serde(deserialize_with = "utils::de_secs_duration")]
Expand All @@ -22,6 +21,26 @@ pub struct SignerConfig {
pub og_eligible_before: DateTime<Utc>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SignerKeys {
#[serde(
rename = "issuerHumanSBT",
deserialize_with = "utils::de_secp256k1_signing_key"
)]
pub issuer_human_sbt: SigningKey,
#[serde(
rename = "issuerOGSBT",
deserialize_with = "utils::de_secp256k1_signing_key"
)]
pub issuer_og_sbt: SigningKey,
#[serde(
rename = "issuerSNOSBT",
deserialize_with = "utils::de_secp256k1_signing_key"
)]
pub issuer_sno_sbt: SigningKey,
}

#[derive(Clone, Debug)]
pub struct SbtRequestSigner {
pub config: SignerConfig,
Expand All @@ -36,16 +55,30 @@ pub struct SignedSBTRequest {
pub s: String,
}

pub enum SBTKind {
Human,
OG,
ServerNodeOperator,
}

impl SbtRequestSigner {
pub fn new(config: SignerConfig) -> Self {
Self { config }
}

fn sign_request(&self, encoded_req: Vec<u8>) -> Result<SignedSBTRequest, AppError> {
let (sign, recovery_id) = self
.config
.signing_key
.sign_digest_recoverable(Keccak256::new_with_prefix(&encoded_req))?;
fn sign_request(
&self,
sbt_kind: SBTKind,
encoded_req: Vec<u8>,
) -> Result<SignedSBTRequest, AppError> {
let signing_key = match sbt_kind {
SBTKind::Human => &self.config.keys.issuer_human_sbt,
SBTKind::OG => &self.config.keys.issuer_og_sbt,
SBTKind::ServerNodeOperator => &self.config.keys.issuer_sno_sbt,
};

let (sign, recovery_id) =
signing_key.sign_digest_recoverable(Keccak256::new_with_prefix(&encoded_req))?;

let (r, s) = sign.split_bytes();

Expand All @@ -69,7 +102,7 @@ impl SbtRequestSigner {
let sbt_expires_at = (datetime + self.config.sbt_lifetime).timestamp() as u64;
let encoded_req = encode_sbt_request(wallet, user_id, req_expires_at, sbt_expires_at);

self.sign_request(encoded_req)
self.sign_request(SBTKind::Human, encoded_req)
}

/// Creates OG SBT request and signs encoded data
Expand All @@ -83,7 +116,7 @@ impl SbtRequestSigner {
let req_expires_at = (datetime + self.config.request_lifetime).timestamp() as u64;
let encoded_req = encode_og_sbt_request(gov_wallet, og_wallet, tx_hash, req_expires_at);

self.sign_request(encoded_req)
self.sign_request(SBTKind::OG, encoded_req)
}

/// Creates SNO SBT request and signs encoded data
Expand All @@ -98,7 +131,7 @@ impl SbtRequestSigner {
let encoded_req =
encode_sno_sbt_request(gov_wallet, sno_wallet, server_nodes_manager, req_expires_at);

self.sign_request(encoded_req)
self.sign_request(SBTKind::ServerNodeOperator, encoded_req)
}
}

Expand All @@ -117,19 +150,38 @@ mod tests {
.unwrap()
.as_u128();
let config = SignerConfig {
signing_key: SigningKey::from_slice(
&hex::decode("356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7")
keys: SignerKeys {
issuer_human_sbt: SigningKey::from_slice(
&hex::decode(
"356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7",
)
.unwrap(),
)
.unwrap(), //SigningKey::random(&mut rand::rngs::OsRng),
)
.unwrap(), //SigningKey::random(&mut rand::rngs::OsRng),
issuer_og_sbt: SigningKey::from_slice(
&hex::decode(
"356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7",
)
.unwrap(),
)
.unwrap(),
issuer_sno_sbt: SigningKey::from_slice(
&hex::decode(
"356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7",
)
.unwrap(),
)
.unwrap(),
},
request_lifetime: Duration::from_secs(180),
sbt_lifetime: Duration::from_secs(86_400),
og_eligible_before: Utc::now(),
};

let wallet = shared::utils::get_eth_address(
config
.signing_key
.keys
.issuer_human_sbt
.verifying_key()
.to_encoded_point(false)
.as_bytes(),
Expand All @@ -151,7 +203,8 @@ mod tests {

// Verify signature
config
.signing_key
.keys
.issuer_human_sbt
.verifying_key()
.verify_digest(
Keccak256::new_with_prefix(hex::decode(&req.data).unwrap()),
Expand Down
31 changes: 25 additions & 6 deletions user-verifier/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ mod tests {
use super::*;
use crate::{
fractal::{UserId, UserStatus},
signer::SignerConfig,
signer::{SignerConfig, SignerKeys},
};

#[test]
Expand All @@ -91,11 +91,29 @@ mod tests {
expires_at: Utc::now(),
};
let signer = SbtRequestSigner::new(SignerConfig {
signing_key: SigningKey::from_slice(
&hex::decode("356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7")
keys: SignerKeys {
issuer_human_sbt: SigningKey::from_slice(
&hex::decode(
"356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7",
)
.unwrap(),
)
.unwrap(),
)
.unwrap(),
issuer_og_sbt: SigningKey::from_slice(
&hex::decode(
"356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7",
)
.unwrap(),
)
.unwrap(),
issuer_sno_sbt: SigningKey::from_slice(
&hex::decode(
"356e70d642cc8ca8c3c502a5d3b210a1791f46c25fab9f8edde2f20f02e33fe7",
)
.unwrap(),
)
.unwrap(),
},
request_lifetime: Duration::from_secs(180),
sbt_lifetime: Duration::from_secs(86_400),
og_eligible_before: Utc::now(),
Expand All @@ -104,7 +122,8 @@ mod tests {
let wallet = shared::utils::get_eth_address(
signer
.config
.signing_key
.keys
.issuer_human_sbt
.verifying_key()
.to_encoded_point(false)
.as_bytes(),
Expand Down
Loading

0 comments on commit 690f73b

Please sign in to comment.