summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/crypto/00_crypto.js68
-rw-r--r--ext/crypto/Cargo.toml1
-rw-r--r--ext/crypto/lib.rs75
3 files changed, 141 insertions, 3 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js
index fdd0f612d..f0ba0b4bf 100644
--- a/ext/crypto/00_crypto.js
+++ b/ext/crypto/00_crypto.js
@@ -1278,6 +1278,28 @@
// 3.
return data.buffer;
}
+ case "spki": {
+ // 1.
+ if (key[_type] !== "public") {
+ throw new DOMException(
+ "Key is not a public key",
+ "InvalidAccessError",
+ );
+ }
+
+ // 2.
+ const data = await core.opAsync(
+ "op_crypto_export_key",
+ {
+ key: innerKey,
+ format: "spki",
+ algorithm: "RSASSA-PKCS1-v1_5",
+ },
+ );
+
+ // 3.
+ return data.buffer;
+ }
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
@@ -1307,6 +1329,29 @@
// 3.
return data.buffer;
}
+ case "spki": {
+ // 1.
+ if (key[_type] !== "public") {
+ throw new DOMException(
+ "Key is not a public key",
+ "InvalidAccessError",
+ );
+ }
+
+ // 2.
+ const data = await core.opAsync(
+ "op_crypto_export_key",
+ {
+ key: innerKey,
+ format: "spki",
+ algorithm: "RSA-PSS",
+ hash: key[_algorithm].hash.name,
+ },
+ );
+
+ // 3.
+ return data.buffer;
+ }
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
@@ -1336,6 +1381,29 @@
// 3.
return data.buffer;
}
+ case "spki": {
+ // 1.
+ if (key[_type] !== "public") {
+ throw new DOMException(
+ "Key is not a public key",
+ "InvalidAccessError",
+ );
+ }
+
+ // 2.
+ const data = await core.opAsync(
+ "op_crypto_export_key",
+ {
+ key: innerKey,
+ format: "spki",
+ algorithm: "RSA-OAEP",
+ hash: key[_algorithm].hash.name,
+ },
+ );
+
+ // 3.
+ return data.buffer;
+ }
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
diff --git a/ext/crypto/Cargo.toml b/ext/crypto/Cargo.toml
index 2aa55599e..d04f8dc33 100644
--- a/ext/crypto/Cargo.toml
+++ b/ext/crypto/Cargo.toml
@@ -24,5 +24,6 @@ rsa = { version = "0.5.0", default-features = false, features = ["std"] }
serde = { version = "1.0.129", features = ["derive"] }
sha-1 = "0.9.7"
sha2 = "0.9.5"
+spki = "0.4.1"
tokio = { version = "1.10.1", features = ["full"] }
uuid = { version = "0.8.2", features = ["v4"] }
diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs
index a562eaf01..2db629c94 100644
--- a/ext/crypto/lib.rs
+++ b/ext/crypto/lib.rs
@@ -271,6 +271,7 @@ pub async fn op_crypto_generate_key(
pub enum KeyFormat {
Raw,
Pkcs8,
+ Spki,
}
#[derive(Deserialize)]
@@ -631,7 +632,27 @@ pub async fn op_crypto_export_key(
Ok(pk_info.to_der().as_ref().to_vec().into())
}
- // TODO(@littledivy): spki
+ KeyFormat::Spki => {
+ // public_key is a PKCS#1 DER-encoded public key
+
+ let subject_public_key = &args.key.data;
+
+ // the SPKI structure
+ let key_info = spki::SubjectPublicKeyInfo {
+ algorithm: spki::AlgorithmIdentifier {
+ // rsaEncryption(1)
+ oid: spki::ObjectIdentifier::new("1.2.840.113549.1.1.1"),
+ // parameters field should not be ommited (None).
+ // It MUST have ASN.1 type NULL.
+ parameters: Some(asn1::Any::from(asn1::Null)),
+ },
+ subject_public_key,
+ };
+
+ // Infallible based on spec because of the way we import and generate keys.
+ let spki_der = key_info.to_vec().unwrap();
+ Ok(spki_der.into())
+ }
// TODO(@littledivy): jwk
_ => unreachable!(),
}
@@ -668,7 +689,31 @@ pub async fn op_crypto_export_key(
Ok(pk_info.to_der().as_ref().to_vec().into())
}
- // TODO(@littledivy): spki
+ KeyFormat::Spki => {
+ // Intentionally unused but required. Not encoded into SPKI (see below).
+ let _hash = args
+ .hash
+ .ok_or_else(|| type_error("Missing argument hash".to_string()))?;
+
+ // public_key is a PKCS#1 DER-encoded public key
+ let subject_public_key = &args.key.data;
+
+ // the SPKI structure
+ let key_info = spki::SubjectPublicKeyInfo {
+ algorithm: spki::AlgorithmIdentifier {
+ // rsaEncryption(1)
+ oid: spki::ObjectIdentifier::new("1.2.840.113549.1.1.1"),
+ // parameters field should not be ommited (None).
+ // It MUST have ASN.1 type NULL.
+ parameters: Some(asn1::Any::from(asn1::Null)),
+ },
+ subject_public_key,
+ };
+
+ // Infallible based on spec because of the way we import and generate keys.
+ let spki_der = key_info.to_vec().unwrap();
+ Ok(spki_der.into())
+ }
// TODO(@littledivy): jwk
_ => unreachable!(),
}
@@ -705,7 +750,31 @@ pub async fn op_crypto_export_key(
Ok(pk_info.to_der().as_ref().to_vec().into())
}
- // TODO(@littledivy): spki
+ KeyFormat::Spki => {
+ // Intentionally unused but required. Not encoded into SPKI (see below).
+ let _hash = args
+ .hash
+ .ok_or_else(|| type_error("Missing argument hash".to_string()))?;
+
+ // public_key is a PKCS#1 DER-encoded public key
+ let subject_public_key = &args.key.data;
+
+ // the SPKI structure
+ let key_info = spki::SubjectPublicKeyInfo {
+ algorithm: spki::AlgorithmIdentifier {
+ // rsaEncryption(1)
+ oid: spki::ObjectIdentifier::new("1.2.840.113549.1.1.1"),
+ // parameters field should not be ommited (None).
+ // It MUST have ASN.1 type NULL.
+ parameters: Some(asn1::Any::from(asn1::Null)),
+ },
+ subject_public_key,
+ };
+
+ // Infallible based on spec because of the way we import and generate keys.
+ let spki_der = key_info.to_vec().unwrap();
+ Ok(spki_der.into())
+ }
// TODO(@littledivy): jwk
_ => unreachable!(),
}