summaryrefslogtreecommitdiff
path: root/extensions/crypto/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/crypto/lib.rs')
-rw-r--r--extensions/crypto/lib.rs133
1 files changed, 133 insertions, 0 deletions
diff --git a/extensions/crypto/lib.rs b/extensions/crypto/lib.rs
index 66e576c6a..d390afdab 100644
--- a/extensions/crypto/lib.rs
+++ b/extensions/crypto/lib.rs
@@ -34,7 +34,9 @@ use ring::signature::EcdsaSigningAlgorithm;
use rsa::padding::PaddingScheme;
use rsa::BigUint;
use rsa::PrivateKeyEncoding;
+use rsa::PublicKey;
use rsa::RSAPrivateKey;
+use rsa::RSAPublicKey;
use sha1::Sha1;
use sha2::Digest;
use sha2::Sha256;
@@ -70,6 +72,7 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
),
("op_crypto_generate_key", op_async(op_crypto_generate_key)),
("op_crypto_sign_key", op_async(op_crypto_sign_key)),
+ ("op_crypto_verify_key", op_async(op_crypto_verify_key)),
("op_crypto_subtle_digest", op_async(op_crypto_subtle_digest)),
("op_crypto_random_uuid", op_sync(op_crypto_random_uuid)),
])
@@ -378,6 +381,136 @@ pub async fn op_crypto_sign_key(
Ok(signature.into())
}
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct VerifyArg {
+ key: KeyData,
+ algorithm: Algorithm,
+ salt_length: Option<u32>,
+ hash: Option<CryptoHash>,
+ signature: ZeroCopyBuf,
+}
+
+pub async fn op_crypto_verify_key(
+ _state: Rc<RefCell<OpState>>,
+ args: VerifyArg,
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Result<bool, AnyError> {
+ let zero_copy = zero_copy.ok_or_else(null_opbuf)?;
+ let data = &*zero_copy;
+ let algorithm = args.algorithm;
+
+ let verification = match algorithm {
+ Algorithm::RsassaPkcs1v15 => {
+ let public_key: RSAPublicKey =
+ RSAPrivateKey::from_pkcs8(&*args.key.data)?.to_public_key();
+ let (padding, hashed) = match args
+ .hash
+ .ok_or_else(|| type_error("Missing argument hash".to_string()))?
+ {
+ CryptoHash::Sha1 => {
+ let mut hasher = Sha1::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::PKCS1v15Sign {
+ hash: Some(rsa::hash::Hash::SHA1),
+ },
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ CryptoHash::Sha256 => {
+ let mut hasher = Sha256::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::PKCS1v15Sign {
+ hash: Some(rsa::hash::Hash::SHA2_256),
+ },
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ CryptoHash::Sha384 => {
+ let mut hasher = Sha384::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::PKCS1v15Sign {
+ hash: Some(rsa::hash::Hash::SHA2_384),
+ },
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ CryptoHash::Sha512 => {
+ let mut hasher = Sha512::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::PKCS1v15Sign {
+ hash: Some(rsa::hash::Hash::SHA2_512),
+ },
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ };
+
+ public_key
+ .verify(padding, &hashed, &*args.signature)
+ .is_ok()
+ }
+ Algorithm::RsaPss => {
+ let salt_len = args
+ .salt_length
+ .ok_or_else(|| type_error("Missing argument saltLength".to_string()))?
+ as usize;
+ let public_key: RSAPublicKey =
+ RSAPrivateKey::from_pkcs8(&*args.key.data)?.to_public_key();
+
+ let rng = OsRng;
+ let (padding, hashed) = match args
+ .hash
+ .ok_or_else(|| type_error("Missing argument hash".to_string()))?
+ {
+ CryptoHash::Sha1 => {
+ let mut hasher = Sha1::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::new_pss_with_salt::<Sha1, _>(rng, salt_len),
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ CryptoHash::Sha256 => {
+ let mut hasher = Sha256::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::new_pss_with_salt::<Sha256, _>(rng, salt_len),
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ CryptoHash::Sha384 => {
+ let mut hasher = Sha384::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::new_pss_with_salt::<Sha384, _>(rng, salt_len),
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ CryptoHash::Sha512 => {
+ let mut hasher = Sha512::new();
+ hasher.update(&data);
+ (
+ PaddingScheme::new_pss_with_salt::<Sha512, _>(rng, salt_len),
+ hasher.finalize()[..].to_vec(),
+ )
+ }
+ };
+
+ public_key
+ .verify(padding, &hashed, &*args.signature)
+ .is_ok()
+ }
+ _ => return Err(type_error("Unsupported algorithm".to_string())),
+ };
+
+ Ok(verification)
+}
+
pub fn op_crypto_random_uuid(
state: &mut OpState,
_: (),