crypto: Move the signature verification method under an Utility struct.
parent
22daf0d81e
commit
89efcee337
|
@ -39,9 +39,10 @@ use crate::{Account, OlmMachine};
|
|||
use crate::{
|
||||
error::{EventError, OlmError, OlmResult, SignatureError},
|
||||
identities::{OwnUserIdentity, UserIdentities},
|
||||
olm::Utility,
|
||||
store::{caches::ReadOnlyUserDevices, Result as StoreResult},
|
||||
verification::VerificationMachine,
|
||||
verify_json, Sas, ToDeviceRequest,
|
||||
Sas, ToDeviceRequest,
|
||||
};
|
||||
|
||||
/// A read-only version of a `Device`.
|
||||
|
@ -362,7 +363,9 @@ impl ReadOnlyDevice {
|
|||
.get_key(DeviceKeyAlgorithm::Ed25519)
|
||||
.ok_or(SignatureError::MissingSigningKey)?;
|
||||
|
||||
verify_json(
|
||||
let utility = Utility::new();
|
||||
|
||||
utility.verify_json(
|
||||
&self.user_id,
|
||||
&DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, self.device_id()),
|
||||
signing_key,
|
||||
|
|
|
@ -28,7 +28,7 @@ use matrix_sdk_common::{
|
|||
identifiers::{DeviceKeyId, UserId},
|
||||
};
|
||||
|
||||
use crate::{error::SignatureError, verify_json, ReadOnlyDevice};
|
||||
use crate::{error::SignatureError, olm::Utility, ReadOnlyDevice};
|
||||
|
||||
/// Wrapper for a cross signing key marking it as the master key.
|
||||
///
|
||||
|
@ -157,7 +157,8 @@ impl MasterPubkey {
|
|||
return Err(SignatureError::UserIdMissmatch);
|
||||
}
|
||||
|
||||
verify_json(
|
||||
let utility = Utility::new();
|
||||
utility.verify_json(
|
||||
&self.0.user_id,
|
||||
&key_id,
|
||||
key,
|
||||
|
@ -191,7 +192,8 @@ impl UserSigningPubkey {
|
|||
|
||||
// TODO check that the usage is OK.
|
||||
|
||||
verify_json(
|
||||
let utility = Utility::new();
|
||||
utility.verify_json(
|
||||
&self.0.user_id,
|
||||
&DeviceKeyId::try_from(key_id.as_str())?,
|
||||
key,
|
||||
|
@ -224,7 +226,8 @@ impl SelfSigningPubkey {
|
|||
|
||||
// TODO check that the usage is OK.
|
||||
|
||||
verify_json(
|
||||
let utility = Utility::new();
|
||||
utility.verify_json(
|
||||
&self.0.user_id,
|
||||
&DeviceKeyId::try_from(key_id.as_str())?,
|
||||
key,
|
||||
|
|
|
@ -44,74 +44,3 @@ pub(crate) use olm::Account;
|
|||
pub use olm::EncryptionSettings;
|
||||
pub use requests::{IncomingResponse, OutgoingRequest, OutgoingRequests, ToDeviceRequest};
|
||||
pub use verification::Sas;
|
||||
|
||||
use error::SignatureError;
|
||||
use matrix_sdk_common::identifiers::{DeviceKeyAlgorithm, DeviceKeyId, UserId};
|
||||
use olm_rs::utility::OlmUtility;
|
||||
use serde_json::Value;
|
||||
|
||||
/// Verify a signed JSON object.
|
||||
///
|
||||
/// The object must have a signatures key associated with an object of the
|
||||
/// form `user_id: {key_id: signature}`.
|
||||
///
|
||||
/// Returns Ok if the signature was successfully verified, otherwise an
|
||||
/// SignatureError.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `user_id` - The user who signed the JSON object.
|
||||
///
|
||||
/// * `key_id` - The id of the key that signed the JSON object.
|
||||
///
|
||||
/// * `signing_key` - The public ed25519 key which was used to sign the JSON
|
||||
/// object.
|
||||
///
|
||||
/// * `json` - The JSON object that should be verified.
|
||||
pub(crate) fn verify_json(
|
||||
user_id: &UserId,
|
||||
key_id: &DeviceKeyId,
|
||||
signing_key: &str,
|
||||
json: &mut Value,
|
||||
) -> Result<(), SignatureError> {
|
||||
if key_id.algorithm() != DeviceKeyAlgorithm::Ed25519 {
|
||||
return Err(SignatureError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
let json_object = json.as_object_mut().ok_or(SignatureError::NotAnObject)?;
|
||||
let unsigned = json_object.remove("unsigned");
|
||||
let signatures = json_object.remove("signatures");
|
||||
|
||||
let canonical_json = cjson::to_string(json_object)?;
|
||||
|
||||
if let Some(u) = unsigned {
|
||||
json_object.insert("unsigned".to_string(), u);
|
||||
}
|
||||
|
||||
let signatures = signatures.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature_object = signatures
|
||||
.as_object()
|
||||
.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature = signature_object
|
||||
.get(user_id.as_str())
|
||||
.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature = signature
|
||||
.get(key_id.to_string())
|
||||
.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature = signature.as_str().ok_or(SignatureError::NoSignatureFound)?;
|
||||
|
||||
let utility = OlmUtility::new();
|
||||
|
||||
let ret = if utility
|
||||
.ed25519_verify(signing_key, &canonical_json, signature)
|
||||
.is_ok()
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SignatureError::VerificationError)
|
||||
};
|
||||
|
||||
json_object.insert("signatures".to_string(), signatures);
|
||||
|
||||
ret
|
||||
}
|
||||
|
|
|
@ -1548,8 +1548,9 @@ pub(crate) mod test {
|
|||
|
||||
use crate::{
|
||||
machine::OlmMachine,
|
||||
olm::Utility,
|
||||
verification::test::{outgoing_request_to_event, request_to_event},
|
||||
verify_json, EncryptionSettings, ReadOnlyDevice, ToDeviceRequest,
|
||||
EncryptionSettings, ReadOnlyDevice, ToDeviceRequest,
|
||||
};
|
||||
|
||||
use matrix_sdk_common::{
|
||||
|
@ -1784,7 +1785,8 @@ pub(crate) mod test {
|
|||
let identity_keys = machine.account.identity_keys();
|
||||
let ed25519_key = identity_keys.ed25519();
|
||||
|
||||
let ret = verify_json(
|
||||
let utility = Utility::new();
|
||||
let ret = utility.verify_json(
|
||||
&machine.user_id,
|
||||
&DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, machine.device_id()),
|
||||
ed25519_key,
|
||||
|
@ -1815,7 +1817,8 @@ pub(crate) mod test {
|
|||
|
||||
let mut device_keys = machine.account.device_keys().await;
|
||||
|
||||
let ret = verify_json(
|
||||
let utility = Utility::new();
|
||||
let ret = utility.verify_json(
|
||||
&machine.user_id,
|
||||
&DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, machine.device_id()),
|
||||
"fake_key",
|
||||
|
@ -1835,7 +1838,8 @@ pub(crate) mod test {
|
|||
|
||||
let mut one_time_key = one_time_keys.values_mut().next().unwrap();
|
||||
|
||||
let ret = verify_json(
|
||||
let utility = Utility::new();
|
||||
let ret = utility.verify_json(
|
||||
&machine.user_id,
|
||||
&DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, machine.device_id()),
|
||||
ed25519_key,
|
||||
|
@ -1857,7 +1861,8 @@ pub(crate) mod test {
|
|||
.await
|
||||
.expect("Can't prepare initial key upload");
|
||||
|
||||
let ret = verify_json(
|
||||
let utility = Utility::new();
|
||||
let ret = utility.verify_json(
|
||||
&machine.user_id,
|
||||
&DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, machine.device_id()),
|
||||
ed25519_key,
|
||||
|
@ -1865,7 +1870,8 @@ pub(crate) mod test {
|
|||
);
|
||||
assert!(ret.is_ok());
|
||||
|
||||
let ret = verify_json(
|
||||
let utility = Utility::new();
|
||||
let ret = utility.verify_json(
|
||||
&machine.user_id,
|
||||
&DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, machine.device_id()),
|
||||
ed25519_key,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
mod account;
|
||||
mod group_sessions;
|
||||
mod session;
|
||||
mod utility;
|
||||
|
||||
pub use account::{Account, AccountPickle, IdentityKeys, PickledAccount};
|
||||
pub use group_sessions::{
|
||||
|
@ -29,6 +30,7 @@ pub(crate) use group_sessions::{GroupSessionKey, OutboundGroupSession};
|
|||
pub use olm_rs::PicklingMode;
|
||||
pub(crate) use session::OlmMessage;
|
||||
pub use session::{PickledSession, Session, SessionPickle};
|
||||
pub(crate) use utility::Utility;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test {
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use olm_rs::utility::OlmUtility;
|
||||
use serde_json::Value;
|
||||
|
||||
use matrix_sdk_common::identifiers::{DeviceKeyAlgorithm, DeviceKeyId, UserId};
|
||||
|
||||
use crate::error::SignatureError;
|
||||
|
||||
pub(crate) struct Utility {
|
||||
inner: OlmUtility,
|
||||
}
|
||||
|
||||
impl Utility {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: OlmUtility::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a signed JSON object.
|
||||
///
|
||||
/// The object must have a signatures key associated with an object of the
|
||||
/// form `user_id: {key_id: signature}`.
|
||||
///
|
||||
/// Returns Ok if the signature was successfully verified, otherwise an
|
||||
/// SignatureError.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `user_id` - The user who signed the JSON object.
|
||||
///
|
||||
/// * `key_id` - The id of the key that signed the JSON object.
|
||||
///
|
||||
/// * `signing_key` - The public ed25519 key which was used to sign the JSON
|
||||
/// object.
|
||||
///
|
||||
/// * `json` - The JSON object that should be verified.
|
||||
pub(crate) fn verify_json(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
key_id: &DeviceKeyId,
|
||||
signing_key: &str,
|
||||
json: &mut Value,
|
||||
) -> Result<(), SignatureError> {
|
||||
if key_id.algorithm() != DeviceKeyAlgorithm::Ed25519 {
|
||||
return Err(SignatureError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
let json_object = json.as_object_mut().ok_or(SignatureError::NotAnObject)?;
|
||||
let unsigned = json_object.remove("unsigned");
|
||||
let signatures = json_object.remove("signatures");
|
||||
|
||||
let canonical_json = cjson::to_string(json_object)?;
|
||||
|
||||
if let Some(u) = unsigned {
|
||||
json_object.insert("unsigned".to_string(), u);
|
||||
}
|
||||
|
||||
let signatures = signatures.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature_object = signatures
|
||||
.as_object()
|
||||
.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature = signature_object
|
||||
.get(user_id.as_str())
|
||||
.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature = signature
|
||||
.get(key_id.to_string())
|
||||
.ok_or(SignatureError::NoSignatureFound)?;
|
||||
let signature = signature.as_str().ok_or(SignatureError::NoSignatureFound)?;
|
||||
|
||||
let ret = if self
|
||||
.inner
|
||||
.ed25519_verify(signing_key, &canonical_json, signature)
|
||||
.is_ok()
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SignatureError::VerificationError)
|
||||
};
|
||||
|
||||
json_object.insert("signatures".to_string(), signatures);
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue