Skip to content

Commit 0cc1aed

Browse files
quextenMGibson1Hinton
authored
[PM-20614] Cose Content Type (#203)
## 🎟️ Tracking https://bitwarden.atlassian.net/browse/PM-20614 ## 📔 Objective Encrypt type 7 (CoseEncrypt0 with currently Xchacha20poly1305) requires specifying a content format. Since the encrypted content is just a byte array, this alone is not enough to understand what format the data contained has. In some cases, multiple formats may be OK. These cases include: - Private keys - PKCS8 DER / CoseKey - Symmetric keys - Bitwarden Custom Key Byte Serialization ("just key bytes concatenated (and padding if it is a CoseKey)"), CoseKey - Utf8 for most cipher fields - Future: - Blob Cipher: Json/Cbor? To distinguish between these, we need to introduce a content format that is passed through until the encryption happens. For AES256-CBC-HMAC, it gets ignored, for CoseEncrypt0/Xchacha20poly1305, it gets written as a protected header onto the encstring/encrypt0 object. We do not add validation on the decryption path in this PR. For key wrapping, when wrapping cosekeys with cosekeys, the Bitwarden Custom Key Byte Serialization with padding is not used, but the raw CoseKey without padding is used; but can be distinguished from other keys on unwrapping by inspecting the content format. Further to ensure the content format is passed along, the encryptable trait is split into 3 traits by this PR. `CompositeEncryptable` is a trait that represents encryption of composite objects. Composite objects here are objects that have sub-encyrptables under the same key. For instance, a cipher is a composite encryptable, since all fields are individually encrypted. It also has some sub-composite encryptables (Uri). Composite encryptables only defer encryption to one of the other traits, and do not themselves encrypt directly, and thus also don't have a content type. For the Utf8 content type specifically, for XChaCha20Poly1305 encryption, a padding scheme is added, in order to hide the direct relationship of ciphertext length to plaintext length. The content type written onto the encrypt0 object is a custom type to indicate this. The since bytes `Vec<u8>`. alone are not enough to carry a content type, a new generic struct `Bytes<ConstContentType>` is introduced and returned in various places such as: - DER private key - DER public key - Symmetric crypto key The `ConstContentType` is sealed and not implementable by other crates, and type aliases are provided for more convenient / less cognitive overhead syntax. For these, the EncryptableWithContentType trait(s) are implemented. ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines <!-- Suggested interactions but feel free to use (or not) as you desire! --> - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes --------- Co-authored-by: Matt Gibson <[email protected]> Co-authored-by: Oscar Hinton <[email protected]>
1 parent b0c950d commit 0cc1aed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1263
-473
lines changed

bitwarden_license/bitwarden-sm/src/projects/create.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::ProjectCreateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

bitwarden_license/bitwarden-sm/src/projects/update.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::ProjectUpdateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

bitwarden_license/bitwarden-sm/src/secrets/create.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::SecretCreateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

bitwarden_license/bitwarden-sm/src/secrets/update.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::SecretUpdateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

crates/bitwarden-core/src/auth/auth_request.rs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub(crate) fn auth_request_decrypt_user_key(
5252
private_key: String,
5353
user_key: UnsignedSharedKey,
5454
) -> Result<SymmetricCryptoKey, EncryptionSettingsError> {
55-
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?;
55+
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?.into())?;
5656
let key: SymmetricCryptoKey = user_key.decapsulate_key_unsigned(&key)?;
5757
Ok(key)
5858
}
@@ -66,7 +66,7 @@ pub(crate) fn auth_request_decrypt_master_key(
6666
) -> Result<SymmetricCryptoKey, EncryptionSettingsError> {
6767
use bitwarden_crypto::MasterKey;
6868

69-
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?;
69+
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?.into())?;
7070
let master_key: SymmetricCryptoKey = master_key.decapsulate_key_unsigned(&key)?;
7171
let master_key = MasterKey::try_from(&master_key)?;
7272

@@ -106,43 +106,45 @@ pub(crate) fn approve_auth_request(
106106
)?)
107107
}
108108

109-
#[test]
110-
fn test_auth_request() {
111-
let request = new_auth_request("[email protected]").unwrap();
112-
113-
let secret = vec![
114-
111, 32, 97, 169, 4, 241, 174, 74, 239, 206, 113, 86, 174, 68, 216, 238, 52, 85, 156, 27,
115-
134, 149, 54, 55, 91, 147, 45, 130, 131, 237, 51, 31, 191, 106, 155, 14, 160, 82, 47, 40,
116-
96, 31, 114, 127, 212, 187, 167, 110, 205, 116, 198, 243, 218, 72, 137, 53, 248, 43, 255,
117-
67, 35, 61, 245, 93,
118-
];
119-
120-
let private_key =
121-
AsymmetricCryptoKey::from_der(&STANDARD.decode(&request.private_key).unwrap()).unwrap();
122-
123-
let encrypted = UnsignedSharedKey::encapsulate_key_unsigned(
124-
&SymmetricCryptoKey::try_from(secret.clone()).unwrap(),
125-
&private_key.to_public_key(),
126-
)
127-
.unwrap();
128-
129-
let decrypted = auth_request_decrypt_user_key(request.private_key, encrypted).unwrap();
130-
131-
assert_eq!(decrypted.to_encoded(), secret);
132-
}
133-
134109
#[cfg(test)]
135110
mod tests {
136111
use std::num::NonZeroU32;
137112

138-
use bitwarden_crypto::{Kdf, MasterKey};
113+
use bitwarden_crypto::{BitwardenLegacyKeyBytes, Kdf, MasterKey, SpkiPublicKeyBytes};
139114

140115
use super::*;
141116
use crate::key_management::{
142117
crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest},
143118
SymmetricKeyId,
144119
};
145120

121+
#[test]
122+
fn test_auth_request() {
123+
let request = new_auth_request("[email protected]").unwrap();
124+
125+
let secret = vec![
126+
111, 32, 97, 169, 4, 241, 174, 74, 239, 206, 113, 86, 174, 68, 216, 238, 52, 85, 156,
127+
27, 134, 149, 54, 55, 91, 147, 45, 130, 131, 237, 51, 31, 191, 106, 155, 14, 160, 82,
128+
47, 40, 96, 31, 114, 127, 212, 187, 167, 110, 205, 116, 198, 243, 218, 72, 137, 53,
129+
248, 43, 255, 67, 35, 61, 245, 93,
130+
];
131+
132+
let private_key =
133+
AsymmetricCryptoKey::from_der(&STANDARD.decode(&request.private_key).unwrap().into())
134+
.unwrap();
135+
136+
let secret = BitwardenLegacyKeyBytes::from(secret);
137+
let encrypted = UnsignedSharedKey::encapsulate_key_unsigned(
138+
&SymmetricCryptoKey::try_from(&secret).unwrap(),
139+
&private_key.to_public_key(),
140+
)
141+
.unwrap();
142+
143+
let decrypted = auth_request_decrypt_user_key(request.private_key, encrypted).unwrap();
144+
145+
assert_eq!(decrypted.to_encoded().to_vec(), secret.to_vec());
146+
}
147+
146148
#[test]
147149
fn test_approve() {
148150
let client = Client::new(None);
@@ -166,8 +168,9 @@ mod tests {
166168
let public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyLRDUwXB4BfQ507D4meFPmwn5zwy3IqTPJO4plrrhnclWahXa240BzyFW9gHgYu+Jrgms5xBfRTBMcEsqqNm7+JpB6C1B6yvnik0DpJgWQw1rwvy4SUYidpR/AWbQi47n/hvnmzI/sQxGddVfvWu1iTKOlf5blbKYAXnUE5DZBGnrWfacNXwRRdtP06tFB0LwDgw+91CeLSJ9py6dm1qX5JIxoO8StJOQl65goLCdrTWlox+0Jh4xFUfCkb+s3px+OhSCzJbvG/hlrSRcUz5GnwlCEyF3v5lfUtV96MJD+78d8pmH6CfFAp2wxKRAbGdk+JccJYO6y6oIXd3Fm7twIDAQAB";
167169

168170
// Verify fingerprint
169-
let pbkey = STANDARD.decode(public_key).unwrap();
170-
let fingerprint = fingerprint("[email protected]", &pbkey).unwrap();
171+
let pubkey = STANDARD.decode(public_key).unwrap();
172+
let pubkey = SpkiPublicKeyBytes::from(pubkey.clone());
173+
let fingerprint = fingerprint("[email protected]", &pubkey).unwrap();
171174
assert_eq!(fingerprint, "childless-unfair-prowler-dropbox-designate");
172175

173176
approve_auth_request(&client, public_key.to_owned()).unwrap();
@@ -181,7 +184,7 @@ mod tests {
181184
let dec = auth_request_decrypt_user_key(private_key.to_owned(), enc_user_key).unwrap();
182185

183186
assert_eq!(
184-
&dec.to_encoded(),
187+
&dec.to_encoded().to_vec(),
185188
&[
186189
201, 37, 234, 213, 21, 75, 40, 70, 149, 213, 234, 16, 19, 251, 162, 245, 161, 74,
187190
34, 245, 211, 151, 211, 192, 95, 10, 117, 50, 88, 223, 23, 157
@@ -200,7 +203,7 @@ mod tests {
200203
.unwrap();
201204

202205
assert_eq!(
203-
&dec.to_encoded(),
206+
&dec.to_encoded().to_vec(),
204207
&[
205208
109, 128, 172, 147, 206, 123, 134, 95, 16, 36, 155, 113, 201, 18, 186, 230, 216,
206209
212, 173, 188, 74, 11, 134, 131, 137, 242, 105, 178, 105, 126, 52, 139, 248, 91,

crates/bitwarden-core/src/auth/login/access_token.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::{Path, PathBuf};
22

33
use base64::{engine::general_purpose::STANDARD, Engine};
4-
use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey};
4+
use bitwarden_crypto::{BitwardenLegacyKeyBytes, EncString, KeyDecryptable, SymmetricCryptoKey};
55
use chrono::Utc;
66
use schemars::JsonSchema;
77
use serde::{Deserialize, Serialize};
@@ -67,7 +67,8 @@ pub(crate) async fn login_access_token(
6767

6868
let payload: Payload = serde_json::from_slice(&decrypted_payload)?;
6969
let encryption_key = STANDARD.decode(&payload.encryption_key)?;
70-
let encryption_key = SymmetricCryptoKey::try_from(encryption_key)?;
70+
let encryption_key = BitwardenLegacyKeyBytes::from(encryption_key);
71+
let encryption_key = SymmetricCryptoKey::try_from(&encryption_key)?;
7172

7273
let access_token_obj: JwtToken = r.access_token.parse()?;
7374

crates/bitwarden-core/src/client/encryption_settings.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ pub enum EncryptionSettingsError {
2727
#[error("Invalid private key")]
2828
InvalidPrivateKey,
2929

30+
#[error("Invalid signing key")]
31+
InvalidSigningKey,
32+
3033
#[error(transparent)]
3134
MissingPrivateKey(#[from] MissingPrivateKeyError),
3235

@@ -49,19 +52,16 @@ impl EncryptionSettings {
4952
signing_key: Option<EncString>,
5053
store: &KeyStore<KeyIds>,
5154
) -> Result<(), EncryptionSettingsError> {
52-
use bitwarden_crypto::{
53-
AsymmetricCryptoKey, CoseSerializable, CryptoError, KeyDecryptable, SigningKey,
54-
};
55+
use bitwarden_crypto::{AsymmetricCryptoKey, CoseSerializable, KeyDecryptable, SigningKey};
5556
use log::warn;
5657

5758
use crate::key_management::{AsymmetricKeyId, SigningKeyId, SymmetricKeyId};
5859

5960
let private_key = {
6061
let dec: Vec<u8> = private_key.decrypt_with_key(&user_key)?;
61-
6262
// FIXME: [PM-11690] - Temporarily ignore invalid private keys until we have a recovery
6363
// process in place.
64-
AsymmetricCryptoKey::from_der(&dec)
64+
AsymmetricCryptoKey::from_der(&dec.into())
6565
.map_err(|_| {
6666
warn!("Invalid private key");
6767
})
@@ -74,8 +74,10 @@ impl EncryptionSettings {
7474
};
7575
let signing_key = signing_key
7676
.map(|key| {
77+
use bitwarden_crypto::CryptoError;
78+
7779
let dec: Vec<u8> = key.decrypt_with_key(&user_key)?;
78-
SigningKey::from_cose(dec.as_slice()).map_err(Into::<CryptoError>::into)
80+
SigningKey::from_cose(&dec.into()).map_err(Into::<CryptoError>::into)
7981
})
8082
.transpose()?;
8183

crates/bitwarden-core/src/key_management/crypto.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use std::collections::HashMap;
88

99
use base64::{engine::general_purpose::STANDARD, Engine};
1010
use bitwarden_crypto::{
11-
AsymmetricCryptoKey, CoseSerializable, CryptoError, EncString, Encryptable, Kdf,
12-
KeyDecryptable, KeyEncryptable, MasterKey, SignatureAlgorithm, SignedPublicKey, SigningKey,
13-
SymmetricCryptoKey, UnsignedSharedKey, UserKey,
11+
AsymmetricCryptoKey, CoseSerializable, CryptoError, EncString, Kdf, KeyDecryptable,
12+
KeyEncryptable, MasterKey, Pkcs8PrivateKeyBytes, PrimitiveEncryptable, SignatureAlgorithm,
13+
SignedPublicKey, SigningKey, SymmetricCryptoKey, UnsignedSharedKey, UserKey,
1414
};
1515
use bitwarden_error::bitwarden_error;
1616
use schemars::JsonSchema;
@@ -536,6 +536,7 @@ pub(super) fn verify_asymmetric_keys(
536536
.decrypt_with_key(user_key)
537537
.map_err(VerifyError::DecryptFailed)?;
538538

539+
let decrypted_private_key = Pkcs8PrivateKeyBytes::from(decrypted_private_key);
539540
let private_key = AsymmetricCryptoKey::from_der(&decrypted_private_key)
540541
.map_err(VerifyError::ParseFailed)?;
541542

@@ -605,8 +606,6 @@ pub fn make_user_signing_keys_for_enrollment(
605606

606607
Ok(MakeUserSigningKeysResponse {
607608
verifying_key: STANDARD.encode(signature_keypair.to_verifying_key().to_cose()),
608-
// This needs to be changed to use the correct COSE content format before rolling out to
609-
// users: https://bitwarden.atlassian.net/browse/PM-22189
610609
signing_key: signature_keypair
611610
.to_cose()
612611
.encrypt(&mut ctx, SymmetricKeyId::User)?,
@@ -845,8 +844,9 @@ mod tests {
845844
let encrypted = enroll_admin_password_reset(&client, public_key.to_owned()).unwrap();
846845

847846
let private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzLtEUdxfcLxDj84yaGFsVF5hZ8Hjlb08NMQDy1RnBma06I3ZESshLYzVz4r/gegMn9OOltfV/Yxlyvida8oW6qdlfJ7AVz6Oa8pV7BiL40C7b76+oqraQpyYw2HChANB1AhXL9SqWngKmLZwjA7qiCrmcc0kZHeOb4KnKtp9iVvPVs+8veFvKgYO4ba2AAOHKFdR0W55/agXfAy+fWUAkC8mc9ikyJdQWaPV6OZvC2XFkOseBQm9Rynudh3BQpoWiL6w620efe7t5k+02/EyOFJL9f/XEEjM/+Yo0t3LAfkuhHGeKiRST59Xc9hTEmyJTeVXROtz+0fjqOp3xkaObAgMBAAECggEACs4xhnO0HaZhh1/iH7zORMIRXKeyxP2LQiTR8xwN5JJ9wRWmGAR9VasS7EZFTDidIGVME2u/h4s5EqXnhxfO+0gGksVvgNXJ/qw87E8K2216g6ZNo6vSGA7H1GH2voWwejJ4/k/cJug6dz2S402rRAKh2Wong1arYHSkVlQp3diiMa5FHAOSE+Cy09O2ZsaF9IXQYUtlW6AVXFrBEPYH2kvkaPXchh8VETMijo6tbvoKLnUHe+wTaDMls7hy8exjtVyI59r3DNzjy1lNGaGb5QSnFMXR+eHhPZc844Wv02MxC15zKABADrl58gpJyjTl6XpDdHCYGsmGpVGH3X9TQQKBgQDz/9beFjzq59ve6rGwn+EtnQfSsyYT+jr7GN8lNEXb3YOFXBgPhfFIcHRh2R00Vm9w2ApfAx2cd8xm2I6HuvQ1Os7g26LWazvuWY0Qzb+KaCLQTEGH1RnTq6CCG+BTRq/a3J8M4t38GV5TWlzv8wr9U4dl6FR4efjb65HXs1GQ4QKBgQC7/uHfrOTEHrLeIeqEuSl0vWNqEotFKdKLV6xpOvNuxDGbgW4/r/zaxDqt0YBOXmRbQYSEhmO3oy9J6XfE1SUln0gbavZeW0HESCAmUIC88bDnspUwS9RxauqT5aF8ODKN/bNCWCnBM1xyonPOs1oT1nyparJVdQoG//Y7vkB3+wKBgBqLqPq8fKAp3XfhHLfUjREDVoiLyQa/YI9U42IOz9LdxKNLo6p8rgVthpvmnRDGnpUuS+KOWjhdqDVANjF6G3t3DG7WNl8Rh5Gk2H4NhFswfSkgQrjebFLlBy9gjQVCWXt8KSmjvPbiY6q52Aaa8IUjA0YJAregvXxfopxO+/7BAoGARicvEtDp7WWnSc1OPoj6N14VIxgYcI7SyrzE0d/1x3ffKzB5e7qomNpxKzvqrVP8DzG7ydh8jaKPmv1MfF8tpYRy3AhmN3/GYwCnPqT75YYrhcrWcVdax5gmQVqHkFtIQkRSCIftzPLlpMGKha/YBV8c1fvC4LD0NPh/Ynv0gtECgYEAyOZg95/kte0jpgUEgwuMrzkhY/AaUJULFuR5MkyvReEbtSBQwV5tx60+T95PHNiFooWWVXiLMsAgyI2IbkxVR1Pzdri3gWK5CTfqb7kLuaj/B7SGvBa2Sxo478KS5K8tBBBWkITqo+wLC0mn3uZi1dyMWO1zopTA+KtEGF2dtGQ=";
848-
let private_key =
849-
AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key).unwrap()).unwrap();
847+
let private_key = STANDARD.decode(private_key).unwrap();
848+
let private_key = Pkcs8PrivateKeyBytes::from(private_key);
849+
let private_key = AsymmetricCryptoKey::from_der(&private_key).unwrap();
850850
let decrypted: SymmetricCryptoKey =
851851
encrypted.decapsulate_key_unsigned(&private_key).unwrap();
852852

@@ -938,11 +938,7 @@ mod tests {
938938
fn test_verify_asymmetric_keys_parse_failed() {
939939
let (user_key, key_pair) = setup_asymmetric_keys_test();
940940

941-
let invalid_private_key = "bad_key"
942-
.to_string()
943-
.into_bytes()
944-
.encrypt_with_key(&user_key.0)
945-
.unwrap();
941+
let invalid_private_key = "bad_key".to_string().encrypt_with_key(&user_key.0).unwrap();
946942

947943
let request = VerifyAsymmetricKeysRequest {
948944
user_key: user_key.0.to_base64(),

crates/bitwarden-core/src/key_management/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
//! - [KeyIds] is a helper type that combines both symmetric and asymmetric key identifiers. This is
77
//! usually used in the type bounds of [KeyStore],
88
//! [KeyStoreContext](bitwarden_crypto::KeyStoreContext),
9-
//! [Encryptable](bitwarden_crypto::Encryptable) and [Decryptable](bitwarden_crypto::Encryptable).
9+
//! [PrimitiveEncryptable](bitwarden_crypto::PrimitiveEncryptable),
10+
//! [CompositeEncryptable](bitwarden_crypto::CompositeEncryptable), and
11+
//! [Decryptable](bitwarden_crypto::Decryptable).
1012
use bitwarden_crypto::{key_ids, KeyStore, SymmetricCryptoKey};
1113

1214
#[cfg(feature = "internal")]

crates/bitwarden-core/src/platform/generate_fingerprint.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ pub enum FingerprintError {
4242

4343
pub(crate) fn generate_fingerprint(input: &FingerprintRequest) -> Result<String, FingerprintError> {
4444
let key = STANDARD.decode(&input.public_key)?;
45-
46-
Ok(fingerprint(&input.fingerprint_material, &key)?)
45+
Ok(fingerprint(&input.fingerprint_material, &key.into())?)
4746
}
4847

4948
/// Errors that can occur when computing a fingerprint.

0 commit comments

Comments
 (0)