-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Arbitrary data signing service (#1350)
- Loading branch information
Showing
5 changed files
with
141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright 2020-2024 IOTA Stiftung | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
syntax = "proto3"; | ||
package utils; | ||
|
||
message DataSigningRequest { | ||
// Raw data that will be signed. | ||
bytes data = 1; | ||
// Signing key's ID. | ||
string key_id = 2; | ||
} | ||
|
||
message DataSigningResponse { | ||
// Raw data signature. | ||
bytes signature = 1; | ||
} | ||
|
||
// Service that handles signing operations on raw data. | ||
service Signing { | ||
rpc sign(DataSigningRequest) returns (DataSigningResponse); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright 2020-2024 IOTA Stiftung | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use _utils::signing_server::Signing as SigningSvc; | ||
use _utils::signing_server::SigningServer; | ||
use _utils::DataSigningRequest; | ||
use _utils::DataSigningResponse; | ||
use identity_iota::storage::JwkStorage; | ||
use identity_iota::storage::KeyId; | ||
use identity_iota::storage::KeyStorageError; | ||
use identity_stronghold::StrongholdStorage; | ||
use tonic::Request; | ||
use tonic::Response; | ||
use tonic::Status; | ||
|
||
mod _utils { | ||
tonic::include_proto!("utils"); | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
#[error("Key storage error: {0}")] | ||
pub struct Error(#[from] KeyStorageError); | ||
|
||
impl From<Error> for Status { | ||
fn from(value: Error) -> Self { | ||
Status::internal(value.to_string()) | ||
} | ||
} | ||
|
||
pub struct SigningService { | ||
storage: StrongholdStorage, | ||
} | ||
|
||
impl SigningService { | ||
pub fn new(stronghold: &StrongholdStorage) -> Self { | ||
Self { | ||
storage: stronghold.clone(), | ||
} | ||
} | ||
} | ||
|
||
#[tonic::async_trait] | ||
impl SigningSvc for SigningService { | ||
#[tracing::instrument( | ||
name = "utils/sign", | ||
skip_all, | ||
fields(request = ?req.get_ref()) | ||
ret, | ||
err, | ||
)] | ||
async fn sign(&self, req: Request<DataSigningRequest>) -> Result<Response<DataSigningResponse>, Status> { | ||
let DataSigningRequest { data, key_id } = req.into_inner(); | ||
let key_id = KeyId::new(key_id); | ||
let public_key_jwk = self.storage.get_public_key(&key_id).await.map_err(Error)?; | ||
let signature = self | ||
.storage | ||
.sign(&key_id, &data, &public_key_jwk) | ||
.await | ||
.map_err(Error)?; | ||
|
||
Ok(Response::new(DataSigningResponse { signature })) | ||
} | ||
} | ||
|
||
pub fn service(stronghold: &StrongholdStorage) -> SigningServer<SigningService> { | ||
SigningServer::new(SigningService::new(stronghold)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,4 @@ mod helpers; | |
mod jwt; | ||
mod sd_jwt_validation; | ||
mod status_list_2021; | ||
mod utils; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright 2020-2024 IOTA Stiftung | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use _utils::signing_client::SigningClient; | ||
use _utils::DataSigningRequest; | ||
use identity_iota::verification::jws::JwsAlgorithm; | ||
use identity_storage::JwkStorage; | ||
use identity_storage::KeyType; | ||
use identity_stronghold::StrongholdStorage; | ||
|
||
use crate::helpers::make_stronghold; | ||
use crate::helpers::TestServer; | ||
|
||
mod _utils { | ||
tonic::include_proto!("utils"); | ||
} | ||
|
||
const SAMPLE_SIGNING_DATA: &'static [u8] = b"I'm just some random data to be signed :)"; | ||
|
||
#[tokio::test] | ||
async fn raw_data_signing_works() -> anyhow::Result<()> { | ||
let stronghold = StrongholdStorage::new(make_stronghold()); | ||
let server = TestServer::new_with_stronghold(stronghold.clone()).await; | ||
|
||
let key_id = stronghold | ||
.generate(KeyType::from_static_str("Ed25519"), JwsAlgorithm::EdDSA) | ||
.await? | ||
.key_id; | ||
|
||
let expected_signature = { | ||
let public_key_jwk = stronghold.get_public_key(&key_id).await?; | ||
stronghold.sign(&key_id, SAMPLE_SIGNING_DATA, &public_key_jwk).await? | ||
}; | ||
|
||
let mut grpc_client = SigningClient::connect(server.endpoint()).await?; | ||
let signature = grpc_client | ||
.sign(DataSigningRequest { | ||
data: SAMPLE_SIGNING_DATA.to_owned(), | ||
key_id: key_id.to_string(), | ||
}) | ||
.await? | ||
.into_inner() | ||
.signature; | ||
|
||
assert_eq!(signature, expected_signature); | ||
|
||
Ok(()) | ||
} |